Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Set data structure in React's state

Is it possible to use ES6's Set data structure in React?

For example, if I have a checklist composed of distinct items, and I'd like to maintain each item's checked state. I'd like to write something like this:

export default class Checklist extends React.Component {   constructor(props) {     super(props);      this.state = {       checkedItems: new Set()     }   }    addItem(item) {     //...?   }    removeItem(item) {     //...?   }    getItemCheckedStatus(item) {     return this.state.checkedItems.has(item);   }    // More code... } 

I understand there may be a problem with the fact that a Set is mutable by nature, and React performs a shallow comparison when updating the component, so it expects immutable objects to be passed and held in the state. However, is there a way to hold and maintain a Set object in the state?

like image 398
mittelmania Avatar asked Jun 11 '17 10:06

mittelmania


People also ask

How do you use set in useState?

You can use the hook like const set = useSetState([]) and then call set. add(el) , set. delete(el) etc..

Can you set state in render React?

render() Calling setState() here makes it possible for a component to produce infinite loops. The render() function should be pure, meaning that it does not modify a component's state. It returns the same result each time it's invoked, and it does not directly interact with the browser.

What happens everytime when there is a change in state data?

Changing the state Object When a value in the state object changes, the component will re-render, meaning that the output will change according to the new value(s).

Can you set state in componentDidMount?

You may call setState() immediately in componentDidMount() . It will trigger an extra rendering, but it will happen before the browser updates the screen.


1 Answers

Since react will identify state changes only if the state property was replaced, and not mutated (shallow compare), you'll have to create a new Set from the old one, and apply the changes to it.

This is possible since new Set(oldSet) !== oldSet.

const oldSet = new Set([1, 2]); const newSet = new Set(oldSet);  console.log(oldSet === newSet);

How you use a Set in a class component:

export default class Checklist extends React.Component {   constructor(props) {     super(props);      this.state = {       checkedItems: new Set()     }          this.addItem = this.addItem.bind(this);     this.removeItem = this.removeItem.bind(this);   }    addItem(item) {     this.setState(({ checkedItems }) => ({       checkedItems: new Set(checkedItems).add(item)     }));   }    removeItem(item) {     this.setState(({ checkedItems }) => {       const newChecked = new Set(checkedItems);       newChecked.delete(item);              return {        checkedItems: newChecked       };     });   }    getItemCheckedStatus(item) {     return this.state.checkedItems.has(item);   }    // More code... } 

How to use a set with the useState() hook:

const Comp = () => {   [state, setState] = useState(() => new Set());    const addItem = item => {     setState(prev => new Set(prev).add(item));   }    const removeItem = item => {     setState(prev => {       const next = new Set(prev);        next.delete(item);        return next;     });   }    return /* JSX */; } 
like image 105
Ori Drori Avatar answered Sep 20 '22 08:09

Ori Drori