可以说我有一个具有条件渲染的视图组件:
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看起来像这样:
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>
);
}
}
可以说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>
);
}
}
似乎一切正常。看起来React只是无法区分’职位-头衔’和’失业原因’。
请告诉我我做错了什么…
可能发生的事情是React认为在渲染之间仅添加了一个MyInput
(unemployment-duration
)。因此,job- title
永不替换为unemployment-reason
,这也是为什么交换预定义值的原因。
当React做比较时,它将根据它们的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>
);
}
}
要么
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执行diff时,它会发现diff
divs
是不同的,并将重新渲染它,包括它的所有子对象(第一个示例)。在第二个示例中,差异比较成功job-title
,unemployment- reason
因为它们现在具有不同的键。
当然,您可以使用任何想要的键,只要它们是唯一的即可。
2017年8月更新
为了更好地了解键在React中的工作方式,我强烈建议阅读我对理解React.js中的唯一键的回答。
2017年11月更新
此更新应该已经发布了一段时间,但是ref
现在不建议使用in中的字符串。例如ref="job-title"
,现在应该改为ref={(el) =>this.jobTitleRef =el}
(例如)。
问题内容: 考虑下面的钩子示例 基本上,我们使用this.forceUpdate()方法强制组件在React类组件中立即重新呈现,如以下示例所示 但是我的查询是如何强制上述功能组件立即使用挂钩重新渲染? 问题答案: 可以使用或进行,因为在内部使用: 不打算在正常情况下使用,仅在测试或其他出色情况下使用。可以以更常规的方式解决这种情况。 是使用不当的例子,是异步的性能,而且不应该被强迫只是因为状态更
但我的问题是我如何强制上面的功能组件重新呈现立即与钩子?
我使用的是ZF2 skeleton应用程序,它有一个.gitignore,可以防止外部库提交到git。在调试过程中,我喜欢在库的源代码中到处更改内容,以了解如何工作。如果这些是版本控制的,将很容易将它们恢复到原始状态。 如何强制Composer重新安装特定的框架,以便再次获得新的未修改副本? PS:请不要建议删除.gitignore文件,因为它存在是有原因的;它阻止我的第三方库进入我的应用程序存储
问题内容: 我有一个功能组件,我想强迫它重新渲染。 我该怎么办? 由于没有实例,因此我无法致电。 问题答案: 现在,使用react挂钩,您可以调用函数组件。 将返回由2个元素组成的数组: 1.一个值,表示当前状态。 2.它的二传手。用它来更新值。 通过设置器更新值将迫使您的功能组件重新呈现 , 就像这样做: 您可以在此处找到演示。 上面的组件使用了自定义的钩子函数(),该函数使用了布尔状态钩子()
问题内容: 我正在努力了解如何在更高阶的组件中正确实现此验证行为。 ========================================== 编辑:TLDR:感谢用户@ noa-dev的出色建议,我在这里创建了一个React Fiddle:https://jsfiddle.net/8nLumb74/1/ 以显示问题。 我究竟做错了什么? 文本框组件: 验证器组件: 父表单组件: 问题答
问题内容: 我在程序开始时,根据数据库中的某些内容,以编程方式在JScrollPane中添加了许多组件(JPanels,JLabels等)。 似乎对于GUI(?)而言,此过程太快了,因此JScrollPane并不总是正确更新,即,即使内部JPanel大于可见区域,滚动条也不可见。 调整窗口大小(JFrame)可以解决此问题,因为我认为Java在调整组件大小时会重新打印它们。 作为测试,我添加了一个