'Setting state in useEffect and then passing as a prop
Not exactly sure why this isn't working I want to set state based on a passed in prop and then pass the state as a prop, but it doesn't work when I use it in a useEffect. I had originally just used a regular function to do this and it worked, but trying to clean up code and it doesn't seem to work.
const Picker = ({choices, activeValue}) => {
const [clickIndex, setClickIndex] = useState(null);
useEffect(() => {
choices.forEach((choice, index) => {
if (activeValue && choice === activeValue) {
setClickIndex(index);
}
});
}, [choices, activeValue]);
return (
<Options
clickedIndex={clickIndex}
/>
);
}
Then in the Options component I set state based on clickedIndex
const [state, setState] = useState({ [clickedIndex]: "clicked" });
The state always ends up as {null: "clicked"} in the Options component. Even though the props shows to be 2.
Before I had done this, just invoking a function for the Picker component instead of useEffect and it worked.
EDIT: Fixed getInitialClicked implementation
const getInitialClicked = () => {
let clickIndex = null;
choices.forEach((choice, index) => {
if (activeValue && choice === activeValue) {
clickIndex = index;
}
}
return clickIndex;
}
return (
<Options
clickedIndex={getInitialClicked()}
/>
);
What am I not understanding with this? Is is bad form to do it the function way or does it not actually matter?
Solution 1:[1]
The value passed to useState only gets checked by React when the component mounts. On further re-renders, the value is ignored, and instead React uses the value that component has in state (passed into it on mount).
A good way to deal with this sort of thing is to not duplicate state between components, because keeping them in sync is a pain and can lead to confusing code. In the Options, remove
const [state, setState] = useState({ [clickedIndex]: "clicked" });
and instead just reference the clickedIndex prop. If you also need an object for rendering or something, construct the object in the main block of the Options function:
const clickedIndexObject = { [clickedIndex]: 'clicked' };
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
