如何在 React 组件上强制重新安装
How to force remounting on React components?
假设我有一个具有条件渲染的视图组件:
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>
);
}
}
我的输入看起来像这样:
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 只是无法区分"职称"和"失业原因"。
请告诉我我做错了什么...
更改组件的键。
<Component key="1" />
<Component key="2" />
组件将被卸载,并且由于密钥已更改,将装载组件的新实例。
记录在 你可能不需要派生状态:
当密钥更改时,React 将创建一个新的组件实例,而不是更新当前组件实例。键通常用于动态列表,但在这里也很有用。
可能发生的情况是 React 认为渲染之间只添加一个MyInput
(unemployment-duration
)。因此,job-title
永远不会被unemployment-reason
替换,这也是交换预定义值的原因。
当 React 进行差异时,它将根据它们的key
属性确定哪些组件是新的,哪些是旧的。如果代码中没有提供这样的密钥,它将生成自己的密钥。
您提供的最后一个代码片段之所以有效,是因为 React 本质上需要更改父div
下所有元素的层次结构,我相信这将触发所有子元素的重新渲染(这就是它工作的原因)。如果将span
添加到底部而不是顶部,则前面元素的层次结构不会更改,并且这些元素不会重新呈现(并且问题将持续存在)。
以下是官方 React 文档的内容:
当孩子被打乱(如在搜索结果中)或将新组件添加到列表的前面(如在流中)时,情况会变得更加复杂。在这些情况下,每个子项的标识和状态必须在渲染通道中维护,您可以通过为其分配一个键来唯一标识每个子项。
当 React 协调键控子项时,它将确保任何带有键的子项都将被重新排序(而不是破坏)或销毁(而不是重用)。
您应该能够通过自己向父div
或所有MyInput
元素提供唯一的key
元素来解决此问题。
例如:
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 执行差异时,它会看到divs
是不同的,并将重新渲染它,包括它的所有子项(第一个示例)。在第二个示例中,差异将在job-title
和unemployment-reason
上取得成功,因为它们现在具有不同的键。
当然,您可以使用任何您想要的键,只要它们是唯一的。
<小时 />2017 年 8 月更新
为了更好地了解键在 React 中的工作原理,我强烈建议阅读我在 React.js 中理解唯一键的答案。
<小时 />2017 年 11 月更新
此更新应该在不久前发布,但现在已弃用在 ref
中使用字符串文本。例如,ref="job-title"
现在应该改为ref={(el) => this.jobTitleRef = el}
(例如)。有关更多信息,请参阅我对使用 this.refs 的弃用警告的回答。
在视图中使用 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>
);
}
}
我正在为我的应用程序开发 Crud。这就是我的做法 得到反应 作为我的依赖。
import React, { useState, setState } from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
import firebase from 'firebase';
// import { LifeCrud } from '../CRUD/Crud';
import { Row, Card, Col, Button } from 'reactstrap';
import InsuranceActionInput from '../CRUD/InsuranceActionInput';
const LifeActionCreate = () => {
let [newLifeActionLabel, setNewLifeActionLabel] = React.useState();
const onCreate = e => {
const db = firebase.firestore();
db.collection('actions').add({
label: newLifeActionLabel
});
alert('New Life Insurance Added');
setNewLifeActionLabel('');
};
return (
<Card style={{ padding: '15px' }}>
<form onSubmit={onCreate}>
<label>Name</label>
<input
value={newLifeActionLabel}
onChange={e => {
setNewLifeActionLabel(e.target.value);
}}
placeholder={'Name'}
/>
<Button onClick={onCreate}>Create</Button>
</form>
</Card>
);
};
那里的一些反应钩子
- 如何在一个yeoman项目中重新安装Grunt
- 如何在 React 组件上强制重新安装
- 在单击时禁用并重新安装图像
- React Router this.context.router.push 不会重新挂载组件
- NodeJS与Node冲突(重新安装NodeJS)
- 当另一个组件发生更改时,React重新渲染组件
- 为什么需要重新打开组件类来指定位置参数
- React Router-在嵌套组件中安装组件
- Rails和ReactJS -重新渲染组件
- React: componentDidMount + setState不重新渲染组件
- 在安装或安装组件上的React抛出错误可能是由于对setState()的快速和频繁调用
- ReactJS+NodeJS:什么是错误"传递--update binary以重新安装或--build fro
- ReactJS -内联样式不会在重新呈现组件时更新
- 重新安装Aptana Studio 3包以获得我的自定义片段
- React JS状态更改没有't重新渲染组件
- 如何重新生成组件、插件等.用于ionic framework app/project
- 动画单个DOM元素而不重新渲染组件
- 3.3 -在每个绑定中重新呈现组件
- 当道具改变时,React会重新发送组件吗
- 可能只在react native中重新渲染组件的一个道具,而不是整个组件