1

So I have a parent component that maps an array of children and these children all have some state hook variable - in the example it's a string, but it could be anything.

When I filter the parent component array, the children mysteriously overtakes the state value from the former array: if the first child had set state to the string "true" - the first child in the NEW array also renders to "true".

I know/think it has to do with js references but I don't know how to fix it!

parent:

function App() {
  const array = ['the', 'cat', 'and', 'the', 'old', 'hat']
  const [words, setWords] = useState(array)

  const filterWords = (e) => {
    setWords(array.filter( a => a.includes(e.target.value)))
  }

  return (
    <div className="App">
      <input type='text' onChange={filterWords} />
    {
      words.map( word => <Sub word={word} />)
    }

    </div>
  );
}

child:

    const [state,
        setState] = useState('false')

    useEffect( () => console.log('rerendered', state) )
    return (
        <div>
            <>{props.word}</>
            <>{state}</>
            <button onClick={() => setState('true')}>set state</button>
        </div>
    )
}

This renders a list that goes like:

the false [set state]

cat false [set state]

...etc

Now I click the first button so it goes

the true [set state]

cat false [set state]

...etc

Then I type the letter 'o' in the search box - now the app renders

old true [set state]

But the "old" child components state was never set to true right? I must be missing something fundamental, but I just don't get it.. Help much appreciated

Simon
  • 13
  • 2
  • 2
    This is probably why React always tells you to use KEY when you're iterating and rendering stuff – TKoL Dec 17 '19 at 15:33
  • Does this answer your question? [Understanding unique keys for array children in React.js](https://stackoverflow.com/questions/28329382/understanding-unique-keys-for-array-children-in-react-js) – Emile Bergeron Dec 17 '19 at 15:42

2 Answers2

3

When you use map to render JSX, the element you render needs a unique key. Keys are how React tracks which elements belong to which values being mapped; without them, if an element changes its position in the array, it can cause issues where React doesn't know which JSX element is from which array element during a re-render.

Assuming every word in the array will be unique, you can do something like this:

{
  words.map( word => <Sub word={word} key={word} />)
}

If the words in the array are NOT unique, you'll need to have some kind of way to create a unique key for each element that will not change even if they move around within the array.

IceMetalPunk
  • 5,476
  • 3
  • 19
  • 26
  • 1
    Thanks a lot, of course this is the reason - actually this is often not well explained in tutorials etc. – Simon Dec 17 '19 at 19:46
0

I think it's because you don't have a key. Try this:

{
  words.map( word => <Sub key={word} word={word} />)
}
TKoL
  • 13,158
  • 3
  • 39
  • 73