如何强制重新安装React组件?

o01*_*o01 84 javascript reactjs

假设我有一个具有条件渲染的视图组件:

render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

MyInput看起来像这样:

class MyInput extends React.Component {

    ...

    render(){
        return (
            <div>
                <input name={this.props.name} 
                    ref="input" 
                    type="text" 
                    value={this.props.value || null}
                    onBlur={this.handleBlur.bind(this)}
                    onChange={this.handleTyping.bind(this)} />
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们说employed是真的.每当我将其切换为false而另一个视图呈现时,只会unemployment-duration重新初始化.还会unemployment-reason预先填充值job-title(如果在条件更改之前给出了值).

如果我将第二个渲染例程中的标记更改为如下所示:

render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <span>Diff me!</span>
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

看起来一切正常.看起来React只是没有分散'职称'和'失业原因'.

请告诉我我做错了什么......

Ale*_*x K 153

更改组件的键.

<Component key="1" />
Run Code Online (Sandbox Code Playgroud)
<Component key="2" />
Run Code Online (Sandbox Code Playgroud)

组件将被卸载,并且由于密钥已更改,因此将安装新的Component实例.

  • 这在React文档中应该更加明显.这完全达到了我的目标,但需要几个小时才能找到. (30认同)
  • 这对我帮助很大!谢谢!我需要重置CSS动画,但唯一的方法是强制重新渲染.我同意这在反应文档中应该更加明显 (4认同)
  • 描述此技术的 React 文档:https://reactjs.org/blog/2018/06/07/you-probously-dont-need-driven-state.html#recommendation-filled-uncontrol-component-with-a-key (2认同)

Chr*_*ris 90

可能发生的是React认为在渲染之间只添加了一个MyInput(unemployment-duration).因此,job-title永远不会被替换unemployment-reason,这也是交换预定义值的原因.

当React执行diff时,它将根据其key属性确定哪些组件是新组件以及哪些组件是旧组件.如果代码中没有提供这样的密钥,它将生成自己的密钥.

您提供的最后一个代码片段之所以起作用,是因为React基本上需要更改父级下所有元素的层次结构,div我相信这会触发所有子级的重新呈现(这就是它工作的原因).如果你添加span到底部而不是顶部,前面元素的层次结构不会改变,并且那些元素不会重新渲染(问题会持续存在).

以下是官方React文档所说的内容:

当孩子们被洗牌时(如在搜索结果中)或者如果新组件被添加到列表的前面(如在流中),情况变得更加复杂.在这些情况下,必须在渲染过程中保持每个孩子的身份和状态,您可以通过为每个孩子分配一个密钥来唯一地识别每个孩子.

当React协调键控子项时,它将确保任何具有键的子项将被重新排序(而不是被破坏)或被销毁(而不是重用).

您应该能够通过key自己向父元素div或所有MyInput元素提供唯一元素来解决此问题.

例如:

render(){
    if (this.state.employed) {
        return (
            <div key="employed">
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div key="notEmployed">
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

要么

render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput key="title" ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <MyInput key="reason" ref="unemployment-reason" name="unemployment-reason" />
                <MyInput key="duration" ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当React执行差异时,它会看到它们divs是不同的并将重新呈现它,包括它的所有'子项(第1个示例).在第二个例子中,diff将成功job-title,unemployment-reason因为它们现在有不同的键.

您当然可以使用您想要的任何键,只要它们是唯一的.


2017年8月更新

为了更好地了解密钥在React中的工作方式,我强烈建议您阅读我在React.js中理解唯一密钥的答案.


2017年11月更新

此更新应该在不久前发布,但ref现在不推荐使用字符串文字.例如ref="job-title",现在应该是ref={(el) => this.jobTitleRef = el}(例如).有关详细信息,请参阅我对使用this.refs的弃用警告的回答.

  • `它将确定哪些组件是新组件,哪些组件是基于其关键属性的旧组件. - 这是......关键...我的理解 (8认同)

Dmi*_*riy 5

setState在视图中使用以更改employed状态属性.这是React渲染引擎的示例.

 someFunctionWhichChangeParamEmployed(isEmployed) {
      this.setState({
          employed: isEmployed
      });
 }

 getInitialState() {
      return {
          employed: true
      }
 },

 render(){
    if (this.state.employed) {
        return (
            <div>
                <MyInput ref="job-title" name="job-title" />
            </div>
        );
    } else {
        return (
            <div>
                <span>Diff me!</span>
                <MyInput ref="unemployment-reason" name="unemployment-reason" />
                <MyInput ref="unemployment-duration" name="unemployment-duration" />
            </div>
        );
    }
}
Run Code Online (Sandbox Code Playgroud)