最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I not include duplicate values in a React state array? - Stack Overflow

programmeradmin0浏览0评论

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
Add a comment  | 

3 Answers 3

Reset to default 12
if (!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}
      />&nbsp;
      <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}
      />&nbsp;
      <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)) {...}
发布评论

评论列表(0)

  1. 暂无评论