This question already has answers here:
React setState not updating state
(11 answers)
Closed 2 years ago.
let [amount, setAmount] = React.useState(100);
function ChangeHandler(event) {
let value = event.target.value;
setAmount(value);
props.update(amount);
}
props.update is a function that I passed from a higher component to update another Hook.
You can't access the state after setting it in next line.
do it like that
let [amount, setAmount] = React.useState(100);
function ChangeHandler(event) {
let value = event.target.value;
setAmount(value);
props.update(value);
}
Related
This question already has answers here:
React Native console.log old value useState
(4 answers)
Closed 3 months ago.
i have problem with onClick function on element in React.
const [selectedGenre, updateSelectedGenre] = React.useState("s");
function update(genre) {
updateSelectedGenre(genre);
console.log(selectedGenre);
}
const Genres = (genreIds) => {
return genreIds.map((genreId, index) => (
<span
style={{
cursor: "pointer",
}}
onClick={() => {
update(genreId);
}}
>
{genreId}{" "}
</span>
));
};
When i click on span first time, console log of selectedGenre is "s",which is default. WHen i click second time, its updated. Why is it like that ? my updateSelectedGenre is before console.log.
Thank you very much.
the setter in useState api is an asynchronous event, therefore you can not trust that calling console.log() will give you the new state.
The desired result can be achieved by
useEffect(() => {
console.log(selectedGenre);
},[selectedGenre]);
Usually inside functions you can't console.log the state right after setting it, because something called as asynchrony, if you really wan't to log the change you should use useEffect
useEffect(() => {console.log(selectedGenre)},[selectedGenre])
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
I am trying to change the values of variables within a useEffect call in js React.
I notice that the values get changed inside of the function, but the global value is not changed.
var O_name = "";
var A_name = "";
var A_platform = "";
var C_name = "";
function Statsview( {backButton} ) {
const urlParams = new URLSearchParams(window.location.search);
const name = urlParams.get('name');
var data = useRef();
const [overwatchName, setO_Name] = useState([]);
useEffect(() => {
console.log('mounted')
database.collection('USERS').where('name','==',name).get().then(snapshot => {
snapshot.forEach(doc => {
var data = doc.data()
O_name = data.overwatch;
console.log(O_name)
A_name = data.apexLegends;
console.log(A_name)
A_platform = data.apexLegendsPlatform;
console.log(A_platform)
C_name = data.chess;
console.log(C_name)
})
}).catch(error => console.log(error))
},[]);
console.log("oname: ",O_name)
console.log("aname: ",A_name)
console.log("aplat: ",A_platform)
console.log("cname: ",C_name)
...
...
}
The console logs inside of the useEffect show updated values for each varaible.
However, the console logs outside of the useEffect show that the values for each variable are blank.
How do I change these global values?
Global variables and functions are initiated when React first load all the scripts, that means when you first load (or reload) the page. React itself is not aware of the mutation of these global variables.
Your code flow is like this.
Global variables are initialized.
console.log() prints the content when a component is loaded.
An async call mutates the global variables => React is not aware of them. hence does not re-render your component. Hence, console.log() is not called.
You should use state hook to store these variables so React knows they are changed.
You should use useRef for this case.
so for simple example.
function MyComponent(){
const A_name = useRef('');
useEffect(() => {
A_name.current = 'new value'
}, []);
}
You can change/access the variable with .current property
You can read more at docs here: https://reactjs.org/docs/hooks-reference.html#useref
It mentioned: useRef returns a mutable ref object whose .current property is initialized to the passed argument (initialValue). The returned object will persist for the full lifetime of the component.
So it would fit your objective
This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Why does calling react setState method not mutate the state immediately?
(9 answers)
Closed 1 year ago.
I am using react to switch between light and dark mode in my website . I also want the theme to persist using localstorage . The problem is that while clicking on switch to toggle the theme the corresponding localstorage theme value does not update. I know that state updates are asynchronous but I want to fix this .
My code:
const [darkMode , setDarkMode] = useState(false);
//change theme
const toggleTheme = ()=>{
setDarkMode(!darkMode);
const root = window.document.documentElement;
if(localStorage.getItem("isDark")=== null){
localStorage.setItem("isDark",darkMode);
}else{
localStorage.setItem("isDark",darkMode);
}
root.classList.toggle('dark');
}
I tried using async await but the result was the same .
You can use useEffect in order to keep watch on darkMode.
Here, useEffect will be called every time when darkMode value is updated. Hence, setting the localStorage value inside. And I removed if.. else.. condition as I guess there is no need of that, if you feel you can keep it.
const [darkMode , setDarkMode] = useState(false);
useEffect(() => {
localStorage.setItem("isDark", darkMode);
}, darkMode);
// change theme
const toggleTheme = ()=>{
setDarkMode(!darkMode);
const root = window.document.documentElement;
root.classList.toggle('dark');
}
You can't use state variable darkMode just after updating it via setDarkMode due to its async nature. You could use useEffect hook but that wont be the best way imo just to solve a simple problem like this. Instead you can use it this way
// Initialize variable from localstorage value
const [darkMode, setDarkMode] = useState(
() => JSON.parse(localStorage.getItem("isDark")) ?? false
);
//change theme
const toggleTheme = () => {
const updatedDarkMode = !darkMode;
setDarkMode(updatedDarkMode);
const root = window.document.documentElement;
localStorage.setItem("isDark", updatedDarkMode);
root.classList.toggle("dark");
};
This question already has answers here:
Console.log showing only the updated version of the object printed
(3 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I'm retrieving data from api and storing it in a sharedState. When i'm trying to access this data like below it seems to return the correct. There is one object in the dashboard array with name field.
console.log(newState.profile)
returns:
However when i access dashboards
console.log(newState.profile.dashboards)
it returns
[]
function to set the state from main.js
export function getProfile(state, user) {
const newState = Object.assign({}, state);
if (user) {
db().collection("users").doc(user.uid)
.onSnapshot((doc) => {
var data = doc.data()
if (data) {
newState.profile.apps = data.apps
newState.profile.dashboards = data.dashboards
} else {
authservice.setUserAcc(user.uid)
}
});
}
return newState
}
i'm not sure wether this is a javascript behaviour or related to the way i did set up the state.
This question already has answers here:
Unable to access React instance (this) inside event handler [duplicate]
(19 answers)
Closed 6 years ago.
I am trying React with ES6, and I am stuck at a point where I am trying to call a function on click of a button, and from that function I need to call another function inside that component only, How do we do that?
Here :
import React from 'react';
export default class StopWatch extends React.Component {
constructor (props) {
super(props);
this.state = {
elapsed : 0,
timer : 0,
isStart : false
}
}
onStartClick () {
setInterval(
() => this.tick1(), 100
);
}
tick1 () {
console.log('tick starts');
}
getTimeSpan (elapsed) {
let m = String(Math.floor(elapsed/1000/60)+100).substring(1);
let s = String(Math.floor((elapsed%(1000*60))/1000)+100).substring(1);
let ms = String(elapsed % 1000 + 1000).substring(1);
return m+":"+s+"."+ms;
}
onResetClick () {
console.log('on click of reset');
}
render() {
return (
<div>
<h1>{this.getTimeSpan(this.state.elapsed)}</h1> <br/>
<button type="button" onClick={this.onStartClick}>Start</button>
<button type="button" onClick={this.onResetClick}>Reset</button>
</div>
);
}
}
I am calling a function "onStartClick" on click of my start button, and inside "onStartClick" function, I am trying to call tick() function, which is giving me an error.
Can anyone suggest me how can we do that ?
What you're after is rebinding. Do it in your constructor once and you'll be set for wherever you want to use that function:
constructor (props) {
super(props);
this.state = {
elapsed : 0,
timer : 0,
isStart : false
}
this.onStartClick = this.onStartClick.bind(this)
this.onResetClick = this.onResetClick.bind(this)
}
For a full understanding of what's going on here, read this: http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/
Understanding how this works is crucial for react - and for all javascript programming.