如何强制重新安装React组件? [英] How to force remounting on React components?

查看:144
本文介绍了如何强制重新安装React组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Lets say I have a view component that has a conditional render:

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>
        );
    }
}

MyInput看起来像这样:

MyInput looks something like this:

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>
        );
    }
}

让我们说就业是真的。每当我将其切换为false而其他视图呈现时,只会重新初始化失业持续时间。此外失业原因预先填入来自 job-title 的值(如果在条件更改之前给出了值) 。

Lets say employed is true. Whenever I switch it to false and the other view renders, only unemployment-duration is re-initialized. Also unemployment-reason gets prefilled with the value from job-title (if a value was given before the condition changed).

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

If I change the markup in the second rendering routine to something like this:

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>
        );
    }
}

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

It seems like everything works fine. Looks like React just fails to diff 'job-title' and 'unemployment-reason'.

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

Please tell me what I'm doing wrong...

推荐答案

可能发生的事情是React认为只有一个 MyInput 失业持续时间)在渲染之间添加。因此,作业标题永远不会被失业原因取代,这也是预定义值的原因所在。交换。

What's probably happening is that React thinks that only one MyInput (unemployment-duration) is added between the renders. As such, the job-title never gets replaced with the unemployment-reason, which is also why the predefined values are swapped.

当React执行差异时,它将根据键财产。如果代码中没有提供这样的密钥,它将生成自己的密钥。

When React does the diff, it will determine which components are new and which are old based on their key property. If no such key is provided in the code, it will generate its own.

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

The reason why the last code snippet you provide works is because React essentially needs to change the hierarchy of all elements under the parent div and I believe that would trigger a re-render of all children (which is why it works). Had you added the span to the bottom instead of the top, the hierarchy of the preceding elements wouldn't change, and those element's wouldn't re-render (and the problem would persist).

这是官方的反应文件说:


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

The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a key.

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

When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).

您应该能够通过向父母提供唯一的密钥元素来解决此问题 div 或所有 MyInput 元素。

You should be able to fix this by providing a unique key element yourself to either the parent div or to all MyInput elements.

例如:

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>
        );
    }
}

OR

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>
        );
    }
}

现在,当React执行差异时,它会看到 divs 是不同的,并将重新呈现它,包括它的所有'孩子(第一个例子)。在第二个例子中,差异将在作业标题失业原因上成功,因为它们现在有所不同密钥。

Now, when React does the diff, it will see that the divs are different and will re-render it including all of its' children (1st example). In the 2nd example, the diff will be a success on job-title and unemployment-reason since they now have different keys.

您可以使用任何您想要的密钥,只要它们是唯一的。

You can of course use any keys you want, as long as they are unique.

2017年8月更新

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

For a better insight into how keys work in React, I strongly recommend reading my answer to Understanding unique keys in React.js.

2017年11月更新

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

This update should've been posted a while ago, but using string literals in ref is now deprecated. For example ref="job-title" should now instead be ref={(el) => this.jobTitleRef = el} (for example). See my answer to Deprecation warning using this.refs for more info.

这篇关于如何强制重新安装React组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆