Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

react / functional component / props changed / getDerivedStateFromProps

Lets say I'm doing a simple CRUD app in react. My functional component is basically just the form.

  • In the CREATE case I pass in an empty object via props
  • In the UPDATE case I pass in an object with the values via props (I got the data in the parent component with an API call)

I looks like this:

const MyForm = (props) => {

 const [myValues, setMyValues] = useState(props.myValues);
 const [errors, setErrors] = useState(0);
 (...)
}

In the UPDATE case, I run (of course) into the issue that props.myValues is still empty when the component is mounted, and not set again (updated) when the api call from the parent component has finished thus leaving the form values empty.

Using a class component, I'd solve that with getDerivedStateFromProps(). Is there anything like that in a functional component? Or am I doing this wrong from the beginning? Thanks for any advice!

like image 297
Thread Pitt Avatar asked Mar 22 '19 12:03

Thread Pitt


People also ask

Do components update when props change?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.

Why functional component is not re rendering even after a prop object change?

There are two common reasons why React might not update a component even though its props have changed: The props weren't updated correctly via setState. The reference to the prop stayed the same.

Why is getDerivedStateFromProps static?

The reason getDerivedStateFromProps is static is to discourage any side-effects during the render phase. For example, updating or using props on the instance. This isn't safe anymore with the upcoming async rendering. It is called when a component is created and each time it recieves a new props.

Can props be changed inside the component?

A component cannot update its own props unless they are arrays or objects (having a component update its own props even if possible is an anti-pattern), but can update its state and the props of its children.


2 Answers

Yes, you can of course use useEffect.

In your case the code should look like this:

const MyForm = (props) => {   const [myValues, setMyValues] = useState(props.myValues);  const [errors, setErrors] = useState(0);   useEffect(() => {    setMyValues(props.myValues);  }, [props.myValues]);  } 
like image 63
Vishal Avatar answered Oct 23 '22 02:10

Vishal


Another way to do this is the Fully uncontrolled component with a key strategy. If you go that route, your component stays the same:

const MyForm = (props) => {   const [myValues, setMyValues] = useState(props.myValues);  const [errors, setErrors] = useState(0);  (...) } 

But there is one extra piece to its usage:

<MyForm myValues={myValues} key={myValues} /> 

Using the key prop like this means a new instance of this component will be created if myValues changes, meaning the default value you have provided to your internal myValues state will be reset to whatever the new values are.

This avoids the double render you get if you useEffect, but comes at the cost of a new component instance. I don't find this to be a problem if you do it at the individual input level, but you may not want to rebuild your whole form.

like image 45
Rob Allsopp Avatar answered Oct 23 '22 02:10

Rob Allsopp