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

IT技术 reactjs
2021-04-22 06:00:22

我偶尔会有一些我想重置的概念上有状态的 React 组件。理想的行为相当于删除旧组件并读取新的原始组件。

React 提供了一种方法setState,允许设置组件自己的显式状态,但不包括浏览器焦点和表单状态等隐式状态,并且也不包括其子项的状态。捕捉所有这些间接状态可能是一项棘手的任务,我更愿意严格而完整地解决它,而不是在每一个新的令人惊讶的状态下玩打地鼠。

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

编辑: 我做了一个简单的例子来演示该this.replaceState(this.getInitialState())方法并将其与方法进行对比this.setState(this.getInitialState())jsfiddle -replaceState更健壮。

4个回答

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

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

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

@EamonNerbonne 在 React 0.8 上,键仅用于区分数组中的同级元素,并在根处被忽略。请参阅github.com/facebook/react/issues/590
2021-05-23 06:00:22
出于好奇,当您说“组件将被丢弃并从头开始创建”时,您的意思是虚拟 DOM 将被丢弃并从头开始创建,但 DOM 更新仍将基于 diff 算法发生?
2021-05-27 06:00:22
这似乎是旧版本的旧答案。这种技术是否仍然适用于 React 16+ 版本?更新的文档似乎没有提到这样的事情。或者我错过了什么?
2021-06-01 06:00:22
@nimgrg 不,真正的 DOM 元素也将被重新创建。(虚拟 DOM 已经在每次渲染时重新创建,所以如果你想保留真实的 DOM,key在这种情况下不要设置 a 。)
2021-06-05 06:00:22
有没有办法从组件内部执行此操作,而无需外部传递关键道具?
2021-06-08 06:00:22

key需要重新初始化的元素添加属性,将在每次更改propsstate关联到元素时重新加载它

键={新日期().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>
  );
}
或者您可以添加一个简单的整数计数器变量作为键
2021-06-01 06:00:22

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

文档说replaceState“可能会在 React 的未来版本中完全删除”。我认为它肯定会被删除,因为replaceState它并不真正符合 React 的哲学。它有助于让 React 组件开始感觉有点瑞士刀。这不利于 React 组件的自然增长,使其变得更小、更有针对性。

在 React 中,如果你必须在泛化或专业化上犯错:瞄准专业化。作为推论,你的组件的状态树应该有一定的简约性(如果你正在搭建一个品牌打屁股的新产品,那么优雅地打破这个规则是很好的)。

无论如何,这就是你的方式。类似于上面 Ben 的(已接受)答案,但像这样:

this.setState(this.getInitialState());

另外(就像 Ben 也说的)为了重置“浏览器状态”,您需要删除该 DOM 节点。利用 vdom 的力量并key为该组件使用新props。新渲染将批发替换该组件。

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

@Graham 我认为将新状态引入尚未在getInitialState. 就像在函数顶部的 JS 函数中声明所有变量一样。旁注:Ben Alpert 的解决方案与我的几乎相同……而且他是 React 的官方维护者!
2021-05-22 06:00:22
如果当前状态包含任何不在初始状态的属性,这将不起作用。虽然我不认为这是一种很好的“状态”,除非你能以某种方式阻止它,但我想避免意外的破坏。我可以接受在某些情况下崩溃的重置,但不能接受巧妙破坏状态的重置。
2021-05-23 06:00:22
不确定我是否遵循。你是说这不等于this.replaceState因为它是。
2021-06-06 06:00:22
@williamle8300 如果在调用之间的组件生命周期中的某处添加一个新属性getInitialState()(例如,在 onClick 处理程序中),则它们不会等效在这种情况下,该新属性在 2nd 之后仍然存在getInitialState()
2021-06-06 06:00:22
我担心函数 getInitialState() 以及因此的答案已被弃用。更新会很好。
2021-06-11 06:00:22

key向元素添加属性并从父元素控制其值的方法可以正常工作。以下是如何使用组件重置自身的示例。

键在父元素中控制,但更新键的函数作为props传递给主元素。这样,重置表单的按钮可以驻留在表单组件本身中。

const InnerForm = (props) => {
  const { resetForm } = props;
  const [value, setValue] = useState('initialValue');

  return (
    <>
      Value: {value}
      <button onClick={() => { setValue('newValue'); }}>
        Change Value
      </button>
      <button onClick={resetForm}>
        Reset Form
      </button>
    </>
  );
};

export const App = (props) => {
  const [resetHeuristicKey, setResetHeuristicKey] = useState(false);
  const resetForm = () => setResetHeuristicKey(!resetHeuristicKey);
  return (
    <>
      <h1>Form</h1>
      <InnerForm key={resetHeuristicKey} resetForm={resetForm} />
    </>
  );
};