命令式程序最重要的特征是状态及其修改。
ReactJs 鼓励尽可能多的函数式编程(例如使用纯度、高阶函数)。我想知道在 ReactJs 中使用不可变状态这个特性是否仍然是一个命令特性,或者可以被认为是功能性的“状态样式”?
从理论上讲,React 状态和纯命令式程序中的状态有什么区别?
命令式程序最重要的特征是状态及其修改。
ReactJs 鼓励尽可能多的函数式编程(例如使用纯度、高阶函数)。我想知道在 ReactJs 中使用不可变状态这个特性是否仍然是一个命令特性,或者可以被认为是功能性的“状态样式”?
从理论上讲,React 状态和纯命令式程序中的状态有什么区别?
从理论上讲,React 状态和纯命令式程序中的状态有什么区别?
在 React中更新状态(使用this.setState
)的全部目的是通知组件状态已更新,并且需要重新渲染。
但是,最终,如果您想在 React 中从状态 A 更改为状态 B,您可以在事件处理程序中执行此操作,如果您愿意,可以强制执行,但必须在不实际更改初始状态的情况下完成。例如
// OK
let foo = this.state.foo;
foo = deriveSomeValue(foo);
this.setState({ foo });
// BAD
this.state.foo = deriveSomeValue(foo);
this.setState(this.state);
在第一个示例中(OK),当然,您可以看到一定程度的杂质;foo
被修改了,但至少原始状态没有。
在第二个示例(BAD)中,我们的杂质水平相同,但更糟;我们直接修改当前状态,这可能会产生不可预测的结果。我看到太多 Stack Overflow 帖子,有人问“为什么我用this.state
??? 做 X 时渲染不正确?” 换句话说,这种不变性范式是出于务实的原因而被强制执行的;也就是说,这就是 React 的设计方式,而任何其他方式都会产生未定义的行为(根据具体情况)。
另一个可能产生不可预测结果的示例:
const foo = this.state.foo;
foo.someProperty = getSomeValue();
this.setState({ foo });
在这种情况下,状态仍然会在通知 React 之前更新。(这与对象被显式引用而不是被隐式复制的事实有关。)
当然,您可以在 React 中以命令式的方式在事件处理程序中从状态 A 转到状态 B,但您必须确保初始状态不会被直接修改。如果您绝对看到需要进行一些复杂的修改,那么我建议您执行对象的深层复制,然后以这种方式进行必要的修改。以下是完全没问题的:
const foo = cloneObject(this.state.foo);
// `cloneObject` is an entirely contrived function. You'll have to pick a
// deep copying library. Google around for "JavaScript deep copying"
foo.someProperty = getSomeValue();
this.setState({ foo });
或者,您可以使用不可变数据结构,这样如果您(在语义上可以称为)直接修改属性,它会产生一个全新的对象,而不必修改原始对象。一个好的库是(正如你提到的)ImmutableJS。
let foo = this.state.foo;
foo = foo.set('someProperty', getSomeValue());
this.setState({ foo });