Sunday, May 19, 2024
 Popular · Latest · Hot · Upcoming
29
rated 0 times [  32] [ 3]  / answers: 1 / hits: 51571  / 7 Years ago, sun, june 11, 2017, 12:00:00

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?


More From » reactjs

 Answers
58

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.


The example adds random integers between 1-5, and then removes random number in the same range.




const { useState } = React;

const Comp = () => {
const [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 (
<div>
<button onClick={() => addItem(Math.ceil(Math.random() * 5))}>Add</button>
<button onClick={() => removeItem(Math.ceil(Math.random() * 5))}>Remove</button>
<div>
{Array.from(state)}
</div>
</div>
);
}

ReactDOM
.createRoot(root)
.render(<Comp />);

<script crossorigin src=https://unpkg.com/react@18/umd/react.development.js></script>
<script crossorigin src=https://unpkg.com/react-dom@18/umd/react-dom.development.js></script>

<div id=root></div>




[#57499] Thursday, June 8, 2017, 7 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
jackelyn

Total Points: 303
Total Questions: 103
Total Answers: 102

Location: Turks and Caicos Islands
Member since Sun, Mar 7, 2021
3 Years ago
jackelyn questions
Thu, Apr 8, 21, 00:00, 3 Years ago
Sun, Feb 28, 21, 00:00, 3 Years ago
Mon, May 25, 20, 00:00, 4 Years ago
Thu, Apr 30, 20, 00:00, 4 Years ago
;