The answer: They're just queues setState , and React. useState create queues for React core to update the state object of a React component. So the process to update React state is asynchronous for performance reasons. That's why changes don't feel immediate.
If you find that useState / setState are not updating immediately, the answer is simple: they're just queues. React useState and setState don't make changes directly to the state object; they create queues to optimize performance, which is why the changes don't update immediately.
useState, the default value will never change, because useState only called once, even the num props changed, the state will never change. Now with useEffect monitor on num props, the child component will get correct value from state. It is common mistake usually happened to new React developer.
When you manage state using the useState hook, all you have to do is call your setState function passing it the initial state. Copied! const resetState = () => { setEmployee(initialState); }; With the useReducer hook, you have to add an action handler for the RESET state that returns the initial state.
The argument passed to useState is the initial state much like setting state in constructor for a class component and isn't used to update the state on re-render
If you want to update state on prop change, make use of useEffect
hook
function Avatar(props) {
const [user, setUser] = React.useState({...props.user});
React.useEffect(() => {
setUser(props.user);
}, [props.user])
return user.avatar ?
(<img src={user.avatar}/>)
: (<p>Loading...</p>);
}
Working demo
Functional components where we use useState
to set initial values to our variable, if we pass initial value through props, it will always set same initial value until you don't make use of useEffect
hook,
for example your case this will do your job
React.useEffect(() => {
setUser(props.user);
}, [props.user])
The function passed to useEffect will run after the render is committed to the screen.
By default, effects run after every completed render, but you can choose to fire them only when certain values have changed.
React.useEffect(FunctionYouWantToRunAfterEveryRender)
if you pass only one argument to useEffect it will run this method after every render
you can decide when to fire this FunctionYouWantToRunAfterEveryRender
by passing second argument to useEffect
React.useEffect(FunctionYouWantToRunAfterEveryRender, [props.user])
as you notice i am passing [props.user] now useEffect
will only fire this FunctionYouWantToRunAfterEveryRender
function when props.user
is changed
i hope this helps your understanding let me know if any improvements are required thanks
you can create your own custom simple hooks for this. The hooks changed default value when it changed.
https://gist.github.com/mahmut-gundogdu/193ad830be31807ee4e232a05aeec1d8
import {useEffect, useState} from 'react';
export function useStateWithDep(defaultValue: any) {
const [value, setValue] = useState(defaultValue);
useEffect(() => {
setValue(defaultValue);
}, [defaultValue]);
return [value, setValue];
}
#Example
const [user, setUser] = useStateWithDep(props.user);
The parameter passed to React.useState()
is only the initial value for that state. React isn't going to recognize that as changing the state, only setting its default value. You'll want to set the default state initially, and then conditionally call setUser(newValue)
, which will be recognized as a new state, and re-render the component.
I would recommend caution updating state without some kind of condition to keep it from constantly updating, and therefore re-rendering everytime props are received. You may want to consider hoisting the state functionality to a parent component and passing the state of the parent down to this Avatar as a prop.
I've created custom hooks like this:
const usePrevious = value => {
const ref = React.useRef();
React.useEffect(() => {
ref.current = value;
}, [value]);
return ref.current;
}
const usePropState = datas => {
const [dataset, setDataset] = useState(datas);
const prevDatas = usePrevious(datas);
const handleChangeDataset = data => setDataset(data);
React.useEffect(() => {
if (!deepEqual(datas, prevDatas)) // deepEqual is my function to compare object/array using deep-equal
setDataset(datas);
}, [datas, prevDatas]);
return [
dataset,
handleChangeDataset
]
}
To use:
const [state, setState] = usePropState(props.datas);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With