首页 > 解决方案 > 为什么在 redux 中使用不可变数据结构时,选择器总是返回不可变的。?

问题描述

根据这里的redux FAQ https://github.com/reduxjs/redux/blob/master/docs/recipes/UsingImmutableJS.md#what-are-some-opinionated-best-practices-for-using-immutable-js -with-redux

“你的选择器应该返回 Immutable.JS 对象”。“总是”。

为什么会这样?

标签: javascriptreduxreact-reduximmutable.jsreselect

解决方案


作为免责声明,情况并非“总是”如此,但文档试图在大多数情况下为您指明正确的方向。

由于 reselect 会记住选择器的返回结果,因此返回一个可变对象会使您容易受到棘手的错误的影响。想象以下场景:

// Immutable State
{
  todos: [{ text: "hey"}, { todo: "text"}]
}

// Selectors

const getTodos = createSelector(state => state.todos, immutableTodos => immutableTodos.toJS())

选择getTodos器返回一个普通的 JS 对象,默认情况下是可变的。现在想象多个使用getTodos选择器的智能组件。

class EditTodos extends PureComponent {
  constructor(props) {
    this.state = { todos: props.todos }
  }

  addUnsavedTodo(newTodo) {
    // Accidentally mutate the return result of getTodos
    const newTodos = this.state.todos.push(newTodo)
    this.setState({ todos: newTodos })
  }

  render() { // Some components for adding unsaved todos }
}

const mapStateToProps = (state) => ({ todos: getTodos(state))

同样使用的第二个组件getTodos会在调用时立即看到新的“未保存”待办事项addUnsavedTodo,这很可能是无意的。getTodos假设 redux未更改,所有对 的调用state都将获得相同的引用,并且任何突变都会影响所有消费者。

上面的示例是人为设计的,但希望它展示了返回纯 JS 对象可能存在风险的原因之一。

此外,正如文档所述您应该限制使用,toJS因为它会影响性能。在选择器中将不可变对象转换为纯 JS 对象没有任何好处


推荐阅读