This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 1 year ago.
I'm building a web page that uses fetch to search information and it shows it to the user.
I've decided to store that information in a state but for some reason it doesn't work the way I expected.
When the data arrives I use setText() and then I print both the 'text' and 'data' variables.
Only 'data' is printing something, 'text' doesn't show anything.
Anyone knows what can be the problem here?
const [text, setText] = useState("")
const getTextFromApi = async () => {
const resp = await fetch(endpoint)
const data = await resp.json()
setText(data)
console.log(data)
console.log("------------------------")
console.log(text)
}
In your example, setText is a function that queues another render of your function and updates the value that will be used for text in that and subsequent renders. It does not update the value of the text variable, which is a local variable.
Edit: this is explained in much more depth here: useState set method not reflecting change immediately
Problem is that set state functions are asynchronous so you don't have the certainty that when you console log the value of the state it was already updated
you could do something like this inside your component
useEffect(() => {
what you execute here will already have the text value set
},[text])
Related
This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 6 days ago.
I am trying to set a state variable using useState hook and then access(console.log) it inside a useEffect hook in a reactjs app. And also I displayed the value of state variable on front end. But the problem is that the state variable's value is displaying correctly on front end but undefined in console.
Actually I want to set the state variable and access it inside the same useEffect hook.
How to solve this?
const [localusername, setlocalusername] = useState();
const [localpassword, setlocalpassword] = useState();
useEffect(() => {
setlocalusername(localStorage.getItem("username"));
setlocalpassword(localStorage.getItem("password"));
console.log(localusername);
console.log(localpassword);
}, []);
Here is the attached snapshot of console...
If you want to get new values of any vars, like useState you must to subscribe it using useEffect.
For example:
useEffect(() => {
setlocalusername(localStorage.getItem("username"));
setlocalpassword(localStorage.getItem("password"));
}, []);
useEffect(() => {
console.log(localusername);
console.log(localpassword);
}, [localusername, localpassword])
This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed last month.
I'm new in React framework and I'm facing following issue: When I'm trying to call backend api after assigning some values, the api is called before the assigned values are updated in the state.
Let me show you the code to get a better understanding:
// define state in RFC
const [item, setItem] = useState("");
// get value when user click submit button
const itemInputOnClickHandler = ()=> {
let comingItemValue = document.getElementById('item-input').value;
setItem(comingItemValue);
submitHandler();
}
// call api
const submitHandler = async() => {
await axios.post("API_URL");
}
// button in html:
<Button label="submit" onClick={itemInputOnClickHandler} className="m-3 btn" />
I tried many aproaches but still get the same result: The api is called before the assigned values are updated in the state.
How can I solve this so the api is called after the state has been updated?
Best not to use DOM functions directly, it's better to store the input value in some sort of state as the user is changing the value, then when it comes to submitting, the value is already available
try something like the following -
// define state in RFC
const [item, setItem] = useState("");
const [inputValue, setInputValue] = useState("");
const onInputChange = (e) => {
setInputValue(e.target.value)
}
// get value when user click submit button
// this is a bit redundant now, you could call submitHandler directly as the onClick handler
const itemInputOnClickHandler = ()=> {
submitHandler();
}
// call api
const submitHandler = async() => {
// inputValue is available here to post
await axios.post("API_URL");
}
// your text input field
<input onChange={onInputChange} ... />
// button in html:
<Button label="submit" onClick={itemInputOnClickHandler} className="m-3 btn" />
As a side note though, the issue you are running into is that setting state is async therefore calling setItem(x) does not set set the value immediately, it would be available in the next render, therefor your API function is grabbing the old value.
In react the state changes do not occur right after. The setState of react is async. It does this because it is an expensive operation and chooses to do many state updates at once to increase efficiency.
If you would like to call the API after the state has been changed , I would suggest adding a callback to the state change and executing the API in the callback function.
Use the useCallback() hook and add the state as a dependency array to execute on every state change.
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 1 year ago.
i'm trying to use trello-web in react.
in the docs it say:
When you have a token, you can do .get, .put, .post and .del, for example:
trello.get('/1/boards').then(console.log)
and everything works fine (with console.log).
But if i want save the response in a variable what i have to change in this line of code to use it in my component?
I dont understand that
.then(console.log)
print in my console and so i cant save it to reuse correctly.
If someone help me to understand.. thanks very much :)
.then(console.log) is a shorthand of .then(event => console.log(event)) (or rather, data). You can write your own function that takes that event as an argument, then do whatever you want with it, for example:
.then(save)
function save(event) {
//do stuff with the event
}
I know you said React, but this should get you going.
If u are using react u can make a state in component eg.
[myData, setMyData] = useState();
Now you can handle incoming data by
trello.get('/1/boards')
returns you a "Promise", you can handle it in two ways
1.
var data = async trello.get('/1/boards')
setMyData(data)
trello.get('/1/boards').then( (data) => { setMyData(data) } )
This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 2 years ago.
This is a popular question among all the new react developers but somehow I'm not able to understand the logic behind available solutions. I'm trying to update the state variable using hooks and trying it read the updated value but always it returns a previous value instead of new value. Below is the sequence of my code execution.
onClick={setTransactionAccountId}
on button click, it executes the below code and updates the state but the console.log shows the old value.
const [accountId, setAccountId] = useState(0);
const setTransactionAccountId = e => {
console.log("Clicked ID:", e.currentTarget.value);
setAccountId(e.currentTarget.value);
console.log("accountId:", accountId);
};
console log:
first button click:
Clicked ID: 0
accountId: 0
second button click:
Clicked ID: 1
accountId: 0
could anyone please tell me the reason behind this behaviour and how to tackle it.
accountId won't have been updated this render. You have to wait for the next render for it to be updated. accountId only gets populated at the top of the function component when useState is called. You're in the middle of the render. If you need the actual value, keep pulling it out of e.currentTarget.value.
From react docs
React may batch multiple setState() calls into a single update for
performance.
Because this.props and this.state may be updated asynchronously, you
should not rely on their values for calculating the next state.
State updates may be batched and updated asynchronously, therefore the state may have not updated when console.log() is called. You will get the guaranteed updated result in your next call to useEffect hook.
This is because setState is asynchronous. Executing console.log('accountId:', accountId) before the state has updated will still give you the previous state value. If you add an async/await, that should fix the issue.
const setTransactionAccountId = async (e) => {
console.log('Clicked ID:', e.currentTarget.value)
await setAccountId(e.currentTarget.value)
console.log('accountId:', accountId)
}
This question already has answers here:
The useState set method is not reflecting a change immediately
(15 answers)
Closed 3 years ago.
I'm quite new to hooks and in react in general. I came accross a problem I couldn't solve so here it is. I have a quotation function that is suppose to calculate the cost price of a benefit.
const quotation = useCallback(()=> {
setCostPrice(0)
keys.forEach(e => {
for (const property in values){
if ((property==e && values[property]==true){
setCostPrice(costPrice + pricing[property])
}
}
})
})
Here is my problem, i'm calling the function quotation() everytime a checkbox is checked (so the cost price will update). The problem is, the function is suppose to "reset" the costprice at 0 everytime it is called but since using "setCostPrice(0)" is asynchronous the result is not the right one. I've read different post concerning using useEffect() but when i'm using useEffect the function can't read the value from values[property].
I don't know how I can fix this issue if anyone wants to help I would appreciate !
If you need to wait for some asynchronous actions, just make your function async and use await inside:
const quotation = useCallback(async ()=> {
await setCostPrice(0)
...
})
Or use .then() if you're not able to apply async/await:
const quotation = useCallback(()=> {
setCostPrice(0).then(() => {
keys.forEach(e => {
...
});
});
})
If this setCostPrice() comes from useState() hook like that:
const [ , setCostPrice ] = useState(...);
You can just provide callback there to receive latest state;
setCostPrice(
oldPrice => { /* return new price from here */ }
);
By the way, you need to provide list of deps for useCallback() hook. Otherwise it won't work.