为什么在 redux 中使用不可变数据结构时选择器总是 return 不可变?
Why should selectors always return immutable when using immutable data structures in 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:
"Your selectors should return Immutable.JS objects"。 "Always"。
为什么会这样?
作为免责声明,"always" 情况并非如此,但文档试图在大多数情况下为您指明正确的方向。
由于 reselect 记忆了选择器的 return 结果,return 使用可变对象会使您容易受到棘手的错误的影响。想象一下以下场景:
// Immutable State
{
todos: [{ text: "hey"}, { todo: "text"}]
}
// Selectors
const getTodos = createSelector(state => state.todos, immutableTodos => immutableTodos.toJS())
getTodos
选择器是 returning 一个普通的 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
后立即看到新的 "unsaved" 待办事项,这很可能是无意的。假设 redux state
不变,对 getTodos
的所有调用将获得相同的引用,并且任何突变都会影响所有消费者。
上面的例子是人为设计的,但希望它能说明 returning 纯 JS 对象可能存在风险的原因之一。
此外,正如文档 mention 所述,您应该限制对 toJS
的使用,因为它会影响性能。将不可变对象转换为选择器中的普通 JS 对象没有任何好处
根据此处的 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:
"Your selectors should return Immutable.JS objects"。 "Always"。
为什么会这样?
作为免责声明,"always" 情况并非如此,但文档试图在大多数情况下为您指明正确的方向。
由于 reselect 记忆了选择器的 return 结果,return 使用可变对象会使您容易受到棘手的错误的影响。想象一下以下场景:
// Immutable State
{
todos: [{ text: "hey"}, { todo: "text"}]
}
// Selectors
const getTodos = createSelector(state => state.todos, immutableTodos => immutableTodos.toJS())
getTodos
选择器是 returning 一个普通的 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
后立即看到新的 "unsaved" 待办事项,这很可能是无意的。假设 redux state
不变,对 getTodos
的所有调用将获得相同的引用,并且任何突变都会影响所有消费者。
上面的例子是人为设计的,但希望它能说明 returning 纯 JS 对象可能存在风险的原因之一。
此外,正如文档 mention 所述,您应该限制对 toJS
的使用,因为它会影响性能。将不可变对象转换为选择器中的普通 JS 对象没有任何好处