在 React 状态下使用 Set 数据结构

IT技术 javascript reactjs
2021-04-22 13:04:08

是否可以Set在 React 中使用 ES6 的数据结构?

例如,如果我有一个由不同项目组成的清单,并且我想维护每个项目的选中状态。我想写这样的东西:

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...
}

我理解 Set 本质上是可变的这一事实可能存在问题,并且 React 在更新组件时执行浅比较,因此它期望传递不可变对象并将其保持在状态中。但是,有没有办法在状态中保持和维护一个 Set 对象?

2个回答

由于只有当 state 属性被替换而不是突变(浅比较)时,react 才会识别状态更改,因此您必须从旧的 Set 中创建一个新的 Set,并将更改应用于它。

这是可能的,因为new Set(oldSet) !== oldSet.

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

console.log(oldSet === newSet);


如何在类组件中使用 Set:

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...
}

如何使用带useState()挂钩的套装

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 */;
}
在删除项的开头有一个额外的括号,这是不需要的,因为我们正在返回一个对象而不是直接改变状态。谢谢你的片段!
2021-05-29 13:04:08
@DBrown - 我不确定你指的是什么。这是setState更新程序方法我已经修复了另一个错误(实际上改变了状态)。
2021-06-09 13:04:08
很好的答案!只需要一个小的更正,下面的行在对象内使用了分号,应该删除: checkedItems: new Set(checkedItems).add(item);
2021-06-09 13:04:08
我重新检查了一遍,虽然我记得它是那个方法中的一个语法错误,但我有一种感觉,它以某种方式来自前一个函数,因为我无法复制。无论如何,再次感谢您的实施蓝图!
2021-06-16 13:04:08

state只是一个普通的对象,你可以在里面放任何你想要的东西。您可以覆盖shouldComponentUpdate生命周期方法来自己实现它。您可以使用自己的逻辑来确定组件是否需要更新。你甚至不需要嵌套你的集合,你可以直接将它设置为state

this.state = new Set();