Lets say I'm doing a simple CRUD app in react. My functional component is basically just the form.
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!
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.
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.
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.
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.
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]); }
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.
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