如何重置包括所有传递可到达状态的React组件?


93

我偶尔会有一些react组件,这些组件在概念上是有状态的,需要重设。理想的行为等同于删除旧组件并读取新的原始组件。

React提供了一种方法setState,该方法允许将组件设置为自己的显式状态,但不包括隐式状态(例如浏览器焦点和表单状态),并且还排除其子级状态。捕获所有这些间接状态可能是一项艰巨的任务,我宁愿严格而彻底地解决它,而不是在每一个令人惊讶的新状态下打个mol子。

是否有API或模式可以做到这一点?

编辑: 我做了一个简单的例子证明了this.replaceState(this.getInitialState())方法并与对比它this.setState(this.getInitialState())的方法:的jsfiddle - replaceState更强劲。

Answers:


206

为确保重置您提到的隐式浏览器状态和子级状态,可以将key属性添加到返回的根级组件中render;当它更改时,该组件将被丢弃并从头开始创建。

render: function() {
    // ...
    return <div key={uniqueId}>
        {children}
    </div>;
}

没有重置单个组件的本地状态的捷径。


1
出于好奇,当您说“组件将被废弃并从头开始创建”时,您是说虚拟DOM将被废弃并从头开始创建,但是DOM更新仍将基于diff算法进行吗?
nimgrg 2014年

1
@nimgrg不,真正的DOM元素也将被重新创建。(虚拟DOM已经在每个渲染器上重新创建,因此,如果要保留真实DOM,key在这种情况下,只需不设置a 。)
Sophie Alpert 2014年

3
@EamonNerbonne在React 0.8上,键仅用于区分数组中的同级元素,并且在根部被忽略。见github.com/facebook/react/issues/590
索菲·阿尔珀特

注意replaceState()getInitialState()都在新的ES6类样式reactjs中弃用。使用this.setState(this._getInitialState())代替。另外,您不能命名自己的状态初始化函数getInitialState()-react会引发警告-调用其他任何方法并state = this._getInitialState()在类的顶层中显式执行。
thom_nic

2
有没有一种方法可以从组件内部执行此操作而无需外部传递关键道具?
trusktr

14

您实际上应该避免replaceState使用它setState

文档说replaceState“可能会在React的未来版本中完全删除”。我认为它肯定会被删除,因为replaceState它并不真正与React的哲学息息相关。它有助于使React组件开始有点瑞士式的感觉。这阻碍了React组件的自然增长,后者变得越来越小,越来越有针对性。

在React中,如果您必须对泛化或专业化有所误解:请寻求专业化。因此,组件的状态树应该具有一定的简约性(如果您要推广具有品牌影响力的新产品,可以很好地打破此规则)。

无论如何,这就是您的做法。与上文Ben(已接受)的答案类似,但是像这样:

this.setState(this.getInitialState());

同样(如Ben所说),为了重置“浏览器状态”,您需要删除该DOM节点。利用vdom的力量,并key为该组件使用新的道具。新的渲染器将替换该组件。

参考:https : //facebook.github.io/react/docs/component-api.html#replacestate


2
如果当前状态包含任何不在初始状态的属性,则此方法将无效。尽管我不认为这是一个伟大的“状态”,但除非您能以某种方式防止这种情况发生,否则我想避免出现意外破损。在某些情况下会崩溃的重置,我可以,但是不会巧妙地破坏状态。
Eamon Nerbonne '16

不确定我是否遵循。您是说这不等于this.replaceState吗?因为是。
wle8300 '16

1
@ williamle8300如果添加新属性来声明两次调用之间getInitialState()(例如,在onClick处理程序中)两次调用之间组件生命周期中的某个位置,则它们将是等效的。在这种情况下,该新属性将在2nd之后仍然存在getInitialState()
格雷厄姆

@Graham我认为将新状态引入尚未在中声明的组件是一种不好的做法getInitialState。就像在函数顶部的JS函数中声明所有变量一样。旁注:Ben Alpert的解决方案与我的解决方案几乎相同……而且他是React的官方维护者!
wle8300 '16

1
恐怕函数getInitialState()和答案都已被弃用。更新会很好。
Martin R.

8

key您需要重新初始化的元素上添加一个属性,将在每次元素更改propsstate与元素更改关联时重新加载该属性。

key = {new Date()。getTime()}

这是一个例子:

render() {
  const items = (this.props.resources) || [];
  const totalNumberOfItems = (this.props.resources.noOfItems) || 0;

  return (
    <div className="items-container">
      <PaginationContainer
        key={new Date().getTime()}
        totalNumberOfItems={totalNumberOfItems}
        items={items}
        onPageChange={this.onPageChange}
      />
    </div>
  );
}

1
或者,您可以添加一个简单的整数计数器变量作为键
极简主义者,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.