在redux中使用不可变数据结构时,为什么选择器总是返回不可变?

时间:2018-12-17 22:51:31

标签: javascript redux react-redux immutable.js reselect

根据https://github.com/reduxjs/redux/blob/master/docs/recipes/UsingImmutableJS.md#what-are-some-opinionated-best-practices-for-using-immutable-js-with-redux的redux常见问题解答:

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

为什么会这样?

1 个答案:

答案 0 :(得分:1)

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

由于重新选择会记住选择器的返回结果,因此返回可变对象会使您容易遇到棘手的错误。想象以下情况:

// 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时立即看到新的“未保存”待办事项,这很可能是无意的。假设redux getTodos不变,所有对state的调用都将获得相同的引用,任何突变都会影响所有使用者。

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

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