Cleanly perform map() over Set collection state but still rerender on state changes?

Viewed 44

I have a Set collection of values. I want to iterate over these and render a component for each value.

I understand I can't use forEach() as I need to return something which is why map() is highly recommended. But again I have a Set and not an Array.

I could use Array.from(set) but it no longer rerenders when the Set state changes, even though I could very well see that the state has indeed changed.

What would be the cleanest way to map() over the values of a Set collection in a state?

...

const [selected, setSelected] = useState(new Set([]))

const addToSelected = data => {
    setSelected(state => state.add(data))
    console.log(selected)
  }

render(
    {selected &&
      Array.from(selected).map(data => {
        return (
          <QuestionsItem
          key={data.message}
          data={data}
          negative
          callback={removeSelected}
          />
       )
    })}
)
1 Answers
  • JavaScript Sets are mutable, which means your .add calls don't change anything that React's basic useState is able to notice; your selected variable stays the same even as you add things to it

A simple approach is to always use an Array and do the duplicate value checking yourself. This will work with minimal fuss:

const [selected, setSelected] = useState([])

const addToSelected = data => {
  if (selected.indexOf(data) === -1) {
    setSelected(state => [...state, data])
  }
  console.log(selected)
}

render(
    selected.map(data => {
      return (
        <QuestionsItem
        key={data.message}
        data={data}
        negative
        callback={removeSelected}
        />
      )
  })
)
Related