【问题标题】:Using a Set data structure in React's state在 React 的状态下使用 Set 数据结构
【发布时间】:2017-06-11 10:30:12
【问题描述】:

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

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

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 对象?

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    由于只有在 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 */;
    }
    

    【讨论】:

    • 在删除项目的开头有一个额外的括号,因为我们返回一个对象而不是直接更改状态,所以不需要它。谢谢sn-p!
    • @DBrown - 我不确定你指的是什么。这是 setState 的 updater method。我已经修复了另一个错误(实际上是在改变状态)。
    • 我重新审查了,虽然我记得这是该方法中的语法错误,但我感觉它在某种程度上来自上一个函数,因为我无法复制。无论如何,再次感谢您的实施蓝图!
    • 很好的答案!只需稍作修正,以下行在对象内使用分号,应将其删除:checkedItems: new Set(checkedItems).add(item);
    【解决方案2】:

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

    this.state = new Set();
    

    【讨论】:

      猜你喜欢
      • 2019-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-13
      • 1970-01-01
      相关资源
      最近更新 更多