Pretty sure I'm missing something fundamental about React.
So here's the code:
export function EditTagsModal({existingTags}) {
console.log('existingTags', existingTags);
const [selectedTags, setSelectedTags] = React.useState(existingTags);
console.log('selectedTags:', selectedTags);
...
}
In a parent component, <EditTagsModal />
is consumed like this:
{tags && <EditTagsModal existingTags={tags} /> }
Here is how it goes down:
existingTags
starts with, say,['hello']
setSelectedTags
is doing its thing.selectedTags
is now['hello', 'world', 'world']
.- Then I send tags to server, close modal, parent re-render.
- Now the
tags
returned by server is['hello', 'world']
, without the duplicates. - Here's the thing: Now I open the modal again, I'm still seeing my values in
selectedTags
(in that second console.log above) that has the duplicates, not thetags
(the first console.log) from my server.
What's up with react?
CodePudding user response:
The selectedTags
state in the useState
hook is only initialized once.
If tags
remains a truthy defined array (even empty arrays are truthy and defined) then the EditTagsModal
component remains mounted by {tags && <EditTagsModal existingTags={tags} />}
. If the tags
value, and thus the existingTags
prop updates and EditTagsModal
is rerendered, then you should implement an useEffect
hook with a dependency on the existingTags
prop to update the local state when the prop value updates.
useEffect(() => {
setSelectedTags(existingTags);
}, [existingTags]);
useEffect
with a dependency array is synonymous to a class component's componentDidMount
and componentDidUpdate
lifecycle methods.
CodePudding user response:
As it is alluded to in the comments, useState(existingTags) (or whatever you call it) will only use existingTags on the first render.
During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState).
After this, on re-renders the useState function does not change the state based on new changes to the props passed in.
export function EditTagsModal(props) {
console.log('existingTags', existingTags);
const { existingTags } = props;
const [selectedTags, setSelectedTags] = React.useState(existingTags);
useEffect(() => { setSelectedTags](existingTags)}, [existingTags] )
console.log('selectedTags:', selectedTags);
...
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>