10

Very simple code here. I'm wondering if this is the expected outcome. I'm upgrading an npm module and it requires I pass these items to useState which was not previously necessary. Unfortunately, I guess this can't be done with useState? Am I right? I'd love to be wrong.


Where props.items contains an array of class-based React components, useState returns an empty array:

const [items, set] = useState(props.items);

Input:

enter image description here

Output:

enter image description here

*Note, images use prop spreading inside of array because I'm out of ideas besides, rework all the things.

2 Answers 2

12

This is not really recommanded you better do it in the useEffect because Props in Initial State is an anti-pattern.

const [items, setItems] = useState([]);


useEffect(() => {
    setItems(props.items);
  },[props.items]);
Sign up to request clarification or add additional context in comments.

5 Comments

this will do set the state only once on mount though. whenever props.items changes in parent it will not be reflected unless props.items is present in dependency array of useEffect
I'm aware, but struggling with very ehhhh pre-release documentation. Let's ignore the fact that it should not be done, can anyone tell me WHY the result is an empty array? That's all I really care about here, although your answer is noted and is important for anyone who happens upon this via Google.
yup of course could you add an example in codesandbox or codepen so we can help
If I could reproduce it in CodeSandbox, I'd certainly have included it. Unfortunately, limited examples I've created in CodeSandbox work as you'd expect, not returning an empty array. Transpilation is fun, I guess. --- set is indeed a reserved word, but I'm not really using the hook as intended at all, in fact, I'm not even using this code anymore. I'm only interested in why the returned array is empty, and that's the case whether I call it set or setItems or anything else.
set is not a reserved word :) @Taki
2

You should have no issues with using react element array as the input to useState. But, whenever you initialize your state with props coming from parent, you also need to re-update your state once the prop from parent changes. Otherwise it will point to the old state passed down from parent in the first pass. And the way to do that is to do a setItems with useEffect hook

useEffect(() => {
   setItems(props.items)
}, [props.items])

btw this will only check for the reference equality between the old and the new array, if you want to do deep comparison, you should probably be using something like use-deep-compare-effect

8 Comments

this is a hard anti-pattern. Why copy props to state instead of just using props? There can't possibly be a single reason to do so
There is one good reason to do it. Trying to follow poor, pre-release documentation, and trying to adhere to it to get a working minimum viable implementation. Once you understand, then you can rip out the anti-pattern. Otherwise, yes; there are really no valid reasons I can think of.
It still applies. Putting it in a useEffect with that dependency only means it will update when the prop changes. Maybe the initial values change based on the URL, but the component never remounts. Maybe the initial values are not immediately available while they are being fetched from a server. Bottom line - Setting state from props is not inherently an anti-pattern. Only when the state does not need to change over time.
@Max I don't know what the author is doing later with the state initialized from the props. I'm merely pointing out what to do to properly re-initialize the value if needed. There are legitimate use cases where you have a component that initialized its state as pointed out by Brian Thompson. And if you don't re-initialize it through useEffect, you won't receive the values if they are changed in parent. Again, depending on the use case, you might not care about later values passed down from parent component. So, all the possibilities are valid based on what your use case is :)
@max exactly. And depending on your use-case you might want that to happen sometimes (I don't know if thats what author intended though :shrug:)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.