How to use Set with react's useState? How to use Set with react's useState? reactjs reactjs

How to use Set with react's useState?


A Set is by definition mutable, React won't trigger a new render if you merely call const newSet = set.add(0) cause the shallow comparison between previous and new will always assert to true

You can use the spread operator to change references between each update yet still maintaining all of Set's behaviors

Adding an element

const [state, setState] = useState(new Set())const addFoo = foo =>{    setState(previousState => new Set([...state, foo]))}

You could still use the add method since it returns the updated set

const addFoo = foo =>{    setState(prev => new Set(prev.add(foo)))}

Removing an element

Removing is a little trickier. You first need to turn it into an array, filter and spread the result

const removeFoo = foo =>{    setState(prev => new Set([...prev].filter(x => x !== foo)))}

For clarity

const removeFoo = foo =>{    const arr = [...state].filter(x => x !== foo)    setState(new Set(arr))}


I followed the following approach and is working pretty well with my React Native component.

const DummyComponent = () => {const [stateUserIds, setStateUseIds] = useState(new Set());........const handleUserSelected = user => {    // Since we cannot mutate the state value directly better to instantiate new state with the values of the state    const userIds = new Set(stateUserIds);    if (userIds.has(user.userId)) {      userIds.delete(user.userId);    } else {      userIds.add(user.userId);    }    setStateUseIds(userIds);  };........return (   <View>        <FlatList          data={dummyUsers}          renderItem={({item, index}) => {            const selected = stateUserIds.has(item.userId);            return (                              <View style={{flex: 2}}>                  <Switch                    isSelected={selected}                    toggleSwitch={() => handleUserSelected(item)}                  />                </View>            );          }}          keyExtractor={(item, index) => item.userId.toString()}        />  </View>)}

Hope this helps someone with same use Case.Please refer to the following Code Sandbox example


You have to create a new set, otherwise react won't know that it needs to rerender. Something like the below will work.

setTags(tags => new Set(tags).add(tag))