Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.useState does not reload state from props

People also ask

Why is useState not updating?

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.

Why React useState setState does not update immediately?

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.

Can you use useState with props?

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.

How do you reset state of useState?

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);