Is this only a syntax difference `useState()` - reactjs

const [val,setVal] = React.useState(0);
Sometimes I see this in other peoples code
setVal(()=>val);
Does that have any difference from this.
setVal(val);

As the comments point out, half the time this syntax makes no difference. Where it does comes into play is asynchronisity. For example, say you have a setTimeout call in a useEffect and it waits a few seconds and then performs a state update, but while awaiting, the state is updated from somewhere else in the component. If you were to reference the state value in the setTimeout callback it would be a stale value and so if you called setMyState(prevState + 1) you would be off by 1. However if you use setMyState(prevState => prevState + 1) you have accessed the most up-to-date state value.
Also, it is very useful when you don't want to reference the state value in a hook like useEffect. Anything included in a dependency array will cause the hook to update and that can produce chain reactions or fire off a useEffect. when using setMyState(prev => prev + 1) inside the hook, you can avoid referencing the state value itself.

Related

React state change is one step behind

A common problem in React, especially among beginners (like me). This is due to the fact that setState is an asynchronous function and React does not change values one by one, but accumulates some pool if it is not otherwise instructed. (please correct me if the wording is wrong)
So here's the question. One simple solution is to put the desired state into the useEffect dependency array.
For example, I have such a component:
const [first, setFirst] = useState()
const [second, setSecond] = useState()
useEffect(() => {
Something logic by first and second...
}, [first])
Here, the useEffect is executed every time the first state changes. At the same time, at the moment of its operation, the second state is not relevant, next time it will become as it should be now, and so on. Always one step behind.
But if I add a second state to the useEffect dependency array, then everything works as it should.
useEffect(() => {
Something logic by first and second...
}, [first, second])
At the same time, it is not necessary that the useEffect work on changing the second state, I added it only in order to have an up-to-date version inside the useEffect. Can I use the useEffect dependency array this way?
if you use useEffect with an empty array it will act as componentDidMount and componentWillUnmount so it will only invoke itself on first component creation and when it is about to unmount.
https://reactjs.org/docs/react-component.html#componentdidmount
Here I got the problem You are facing, I am not fully sure, but In my case I was console.log(result) withing the fucntion that was changing state, but it was always one step behind. why was that? because in React it is considered as side effect. So If you console.log(result) in useEffect passing the value in dependency array then, it will console log the same value that instantly changed.
In backgorund the state is updating exactly the same time but useEffect detects it as exactly as it is changed.
You can write any logic in useEffect as well or in the function which you are updating.
So there should not be any problem writing logic in the function which you are callilng on click.

Why would a value get stale using closure in React?

In the documentation for useEffect() it shows the following example:
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
}
It then says:
Experienced JavaScript developers might notice that the function
passed to useEffect is going to be different on every render. This is
intentional. In fact, this is what lets us read the count value from
inside the effect without worrying about it getting stale. Every time
we re-render, we schedule a different effect, replacing the previous
one.
I don't understand why count would get stale inside useEffect() since useEffect has count within its closure. Since useEffect() is a hook, shouldn't it always have access to the latest state variable? Also, in general, how can I be sure that I always have the latest value for a state variable?
I don't understand why count would get stale inside useEffect() since useEffect has count within its closure.
Keep in mind that Example is going to be called multiple times, once for every render. So there are N renders, N count variables, and N useEffect functions. So it's true that each effect function has count within its closure, but each of them has a specific count within its closure. Whatever value it had when the closure was created, that's the value it will have when the effect runs. If you only created the function once, closing over the first value of count, then that code would only ever see the first value of count (ie, 0).
Also, in general, how can I be sure that I always have the latest value for a state variable?
If you're setting state, then you can always access the latest value by using the function version of setState. For example:
setCount(prev => /* calculate new state from prev */)`
For other cases, either include the state in the dependency array of your useEffect, so that the effect re-runs when the count changes:
useEffect(() => {
// some code that uses `count`
}, [count]);
Or leave the dependency array off entirely if you want the effect to run on every render.
useEffect(() => {
// some code that uses `count`
});

React js state value late update

set the state value in Useeffect function and want to use that value after 5 lines in filter function but the state show the empty value means it update the state late how to solve this error
setState is an asynchronous function. Let's take this example
const [testState, setTestState] = useState()
and in a useEffect, if you call lets say setTestState('1234') and the very next line you try to log it console.log(testState) - this wont log '123' as the setTestState is asynchronous, which is happening in your case.
Solution -
Put the filter function in a different useEffect and pass the state in the dependency array

understanding async behavior of use Effect hook working

const [count,setCount]=useState(5)
useEffect(()=>{
setCount(10)},[count])
In above code if i am updating state without async operation useEffect doesn't goes to infite loop.While in below code if i update sate through asysnc operation it goes to infite loop can some one tell me the behavior of useEffect in the case of async oeration?
const [count,setCount]=useState(5)
useEffect(()=>{
//some async operation
.then(response)=>{
setCount(response.data)}},[count])
This is because numbers are compared to values and objects by references. Each time async operation result in new object reference, hence useEffect triggers.
In case of number like setCount(5) will not trigger again as second time 5 is the same variable as previous.
Thats a good question!
In the first snippet you were setting the count to 10, that value is not changing dynamically and hence it will change once and wait for the count to change again which will not happen over there, whereas in the second snippet once the async operation is completed it will update the count and because of this count update useEffect will be triggered again along with the async operation in it. So it goes into a recursive updation.
If you want, you can change the first snippet like this to see the recursive updation
setCount(count + 1);
This is the catch of hooks and how they update state, if your previous state value and current state value is same then react functional component won't re-renders, so it is advisable if you are working with object type of state then always create new object or use spread operator for updating any property inside object while updating your state. In your case setCount(10) will always return a constant value of 10 so useEffect won't trigger infinite times as count is theoretically changed once from 5 to 10, but for an API request it will always returns an object with new reference so it'll create an infinite loop. You can also do setCount(10) inside your API result and it also won't trigger useEffect as count is basically never changed from 10 except from a change 5 to 10.

What is the point of the props argument in the setState async setting function

In React when you want to update state based on a previous value of the state, due to some asynchronous qualities about the setState method, you need to pass in a function as the first param so that at the time state is actually being updated setState has access to the most up to date version of the state. e.g.
const setStateCallback = prevState => {
return {myInteger: prevState.myInteger + this.props.step};
}
this.setState(setStateCallback);
My question is what is the point of the props argument in this function if state is the only piece of data is potentially out of date. Why not just use
const setStateCallback = prevState => {
return {myInteger: prevState.myInteger + this.props.step};
}
this.setState(setStateCallback);
The way I assume setState is working is that setStateCallback gets stored and will be invoked once React is ready to process all of the setState calls. At that time, yes I would need to have access to the state updates that have happened during with other setState calls in the process. However, when setStateCallback is called any updates that were made to this.props.step in the meantime would still be available on this.props.step because I am referencing the this.props object. If I did this
const step = this.props.step
const setStateCallback = prevState => {
return {myInteger: prevState.myInteger + step};
}
this.setState(setStateCallback);
This is a problem because the value of step (assuming this is a Number or String) is no longer being referenced off the props object and could be out of date.
So given my assumptions are correct, accessing the props argument given to the callback setStateCallback seems unnecessary.
UPDATE
As pointed out by Brad Bumbalough, and a little extra evidence by myself below, the props arg is indeed necessary.
The implications of this finding mean you must be careful whenever accessing this.state or this.props within your custom class methods. For example, for any custom class methods called within a setState callback you need to make sure that any references within those methods or references within subsequent class methods made from that call take state and props as arguments and don't refer to the this.props or this.state.
I think their point is that everything is asynchronous. So, if you are expressly depending on props for your state change, you can't be 100% certain that this.props hasn't changed after the setState call is first queued.
A possible lifecycle of when this would be a problem could be...
Initial render.
Async call to get data from server.
User interaction triggers a setState call that depends on current props (prevState.myInteger + props.step). This will be evaluated immediately with current state/props, and the result gets stored as the new value for the state attribute.
setState call is queued.
Async call returns and updates parent component/store, trigging props to change.
setState call is processed and applied, but the props used to generate the stored state data is now out of sync with the current props the user can see, leading to confusion, chaos, and WW3. Ok, I might have exaggerated there.
The key is that it might change. 99% of the time you probably won't need to drill this specific into the call. But the call is there, if you so need it.
In case anyone else was looking, here's the link to the docs on this.
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.
To fix it, use a second form of setState() that accepts a function rather than an object. That function will receive the previous state as the first argument, and the props at the time the update is applied as the second argument.

Resources