I want to make sure that I can't push a duplicated value into an array in a React state. The duplicated value is still going in the array though.
I have tried using .includes
but it is not working.
const categoryCheck = (category) => {
let categories = [...this.state.categories]
if (this.state.categories === undefined) {
return
}
console.log(categories, category)
console.log(!categories.includes(category))
if (!categories.includes(category) === false) {
categories.push(category)
console.log('new category', categories)
}
}
input: 'cat'
Expected result: ['cat']
Actual result: ['cat', 'cat']
UPDATE: This is my function and this is how I call it. Thanks for all the help!
uniqueCategories = category => {
//makes sure that there are no duplicate categories in array
if (category === undefined) {
return;
}
let categories = new Set(category);
categories = Array.from(categories);
console.log(categories);
return categories;
};
I call it in another function like this:
this.setState({
categories: this.uniqueCategories([
...this.state.categories,
categoryInput
])
I want to make sure that I can't push a duplicated value into an array in a React state. The duplicated value is still going in the array though.
I have tried using .includes
but it is not working.
const categoryCheck = (category) => {
let categories = [...this.state.categories]
if (this.state.categories === undefined) {
return
}
console.log(categories, category)
console.log(!categories.includes(category))
if (!categories.includes(category) === false) {
categories.push(category)
console.log('new category', categories)
}
}
input: 'cat'
Expected result: ['cat']
Actual result: ['cat', 'cat']
UPDATE: This is my function and this is how I call it. Thanks for all the help!
uniqueCategories = category => {
//makes sure that there are no duplicate categories in array
if (category === undefined) {
return;
}
let categories = new Set(category);
categories = Array.from(categories);
console.log(categories);
return categories;
};
I call it in another function like this:
this.setState({
categories: this.uniqueCategories([
...this.state.categories,
categoryInput
])
Share
Improve this question
edited May 6, 2019 at 7:16
Lee
asked May 6, 2019 at 2:51
LeeLee
1351 gold badge2 silver badges12 bronze badges
1
- You can use dictionary as stackoverflow.com/questions/1208222, Or remove duplicated value as stackoverflow.com/questions/9229645 – Wang Liang Commented May 6, 2019 at 2:54
3 Answers
Reset to default 12if (!categories.includes(category) === false) {
is a double negative. Remove the === false
.
An alternative is to use a Set
for uniqueness since it automatically discards duplicates. Typically, sets offer fast lookup time, but for small amounts of data the performance is probably not much different than array with includes
since both structures are rebuilt on every render.
Here's a toy example of using Set
:
const App = () => {
const [categories, setCategories] = React.useState(new Set());
const [item, setItem] = React.useState("");
const addCategory = e => {
if (item.trim()) {
setCategories(prevState => new Set(prevState).add(item.trim()));
}
};
return (
<div>
<input
onChange={e => setItem(e.target.value)}
value={item}
/>
<button onClick={addCategory}>Add Item</button>
<ul>{[...categories].map(e => <li key={e}>{e}</li>)}</ul>
</div>
);
};
ReactDOM.createRoot(document.querySelector("#app"))
.render(<App />);
<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="app"></div>
And an includes
example:
const Example = () => {
const [categories, setCategories] = React.useState([]);
const [item, setItem] = React.useState("");
const addCategory = e => {
const trimmed = item.trim();
if (trimmed && !categories.includes(trimmed)) {
setCategories(prevState => prevState.concat(trimmed));
}
};
return (
<div>
<input
onChange={e => setItem(e.target.value)}
value={item}
/>
<button onClick={addCategory}>Add Item</button>
<ul>{categories.map(e => <li key={e}>{e}</li>)}</ul>
</div>
);
};
ReactDOM.createRoot(document.querySelector("#app"))
.render(<Example />);
<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="app"></div>
You can use Set
in ES6
const categoryCheck = (category) => {
if (this.state.categories === undefined) {
return
}
let categories = new Set(this.state.categories)
categories.add(category)
this.setState({ categories: Array.from(categories) })
}
Your logic is reversed:
if (!categories.includes(category) === false) {...}
Will return true
if the item is not in the array. Just use this:
if (!categories.includes(category)) {...}