如何在 redux-form 的 <Field> 中有条件地渲染组件
How to conditionally render component in <Field> of redux-form
在我的代码中,试图通过一个名为 renderDatePicker()
的函数在 Redux Form 的 <Field>
组件中呈现 <DatePicker>
。此函数链接到 handleClick()
函数,其中状态变量 isOpen
设置为 true
。
所以理想情况下,onClick
应该呈现 <DatePicker>
,因为它设置为可见。但是代码不会更新任何东西。我哪里做错了?
注意:在没有 <Field component=...>
的帮助下直接单独渲染 <DatePicker>
,效果很好。
用于调试,完整代码在CodeSandbox中,
SimpleForm.js
import React from "react";
import { reduxForm } from "redux-form";
import { Field } from "redux-form";
import DatePicker from "react-mobile-datepicker";
class SimpleForm extends React.Component {
constructor(props) {
super(props);
this.state = {
time: new Date(),
isOpen: false
};
this.handleClick = this.handleClick.bind(this);
}
renderDatePicker = () => (
<DatePicker
value={this.state.time}
isOpen={this.state.isOpen}
onSelect={this.handleSelect}
onCancel={this.handleCancel}
/>
);
handleClick() {
this.setState({ isOpen: true }, function() {
console.log(this.state.isOpen);
});
}
handleCancel = () => {
this.setState({ isOpen: false });
};
handleSelect = time => {
this.setState({ time, isOpen: false });
};
render() {
return (
<div>
<button className="select-btn" onClick={this.handleClick}>
select time
</button>
<Field
name="date"
type="date"
component={this.renderDatePicker}
label={"date"}
/>
</div>
);
}
}
export default reduxForm({
form: "simple" // a unique identifier for this form
})(SimpleForm);
这种行为的原因在于 react-form 的 Field
组件的实现。它对其所有属性进行浅层比较,以决定是否应该重新渲染。您可以随意更改组件的 state
,对 this.renderDatePicker
的引用不会更改。
Field
将包括 onChange
处理程序和当前 value
的属性传递到字段的 component
无状态函数调用中以通知更改,但这实际上并不是在此处申请,因为您的切换按钮在该字段之外。
所以我想到的一个选择是将您的按钮移动到呈现的字段中,然后调用 onChange(!value)
。
更简单但更肮脏的选择是在你的 component
属性 中使用箭头函数:component={() => this.renderDatePicker()}
- 这个实例随着你的 [=20= 的每次重新渲染而改变](即如果 state
发生变化),因此它会带来成本,但根据您应用程序的复杂性,成本可以忽略不计。为了减轻影响,您可以实现 shouldComponentUpdate
(就像 redux-form 的 Field
所做的那样)来根据当前和下一个 isOpen
状态决定是否应该重新渲染。
在 redux-form 中查看此位以获取更多详细信息:https://github.com/erikras/redux-form/blob/master/src/createField.js#L44
在我的代码中,试图通过一个名为 renderDatePicker()
的函数在 Redux Form 的 <Field>
组件中呈现 <DatePicker>
。此函数链接到 handleClick()
函数,其中状态变量 isOpen
设置为 true
。
所以理想情况下,onClick
应该呈现 <DatePicker>
,因为它设置为可见。但是代码不会更新任何东西。我哪里做错了?
注意:在没有 <Field component=...>
的帮助下直接单独渲染 <DatePicker>
,效果很好。
用于调试,完整代码在CodeSandbox中,
SimpleForm.js
import React from "react";
import { reduxForm } from "redux-form";
import { Field } from "redux-form";
import DatePicker from "react-mobile-datepicker";
class SimpleForm extends React.Component {
constructor(props) {
super(props);
this.state = {
time: new Date(),
isOpen: false
};
this.handleClick = this.handleClick.bind(this);
}
renderDatePicker = () => (
<DatePicker
value={this.state.time}
isOpen={this.state.isOpen}
onSelect={this.handleSelect}
onCancel={this.handleCancel}
/>
);
handleClick() {
this.setState({ isOpen: true }, function() {
console.log(this.state.isOpen);
});
}
handleCancel = () => {
this.setState({ isOpen: false });
};
handleSelect = time => {
this.setState({ time, isOpen: false });
};
render() {
return (
<div>
<button className="select-btn" onClick={this.handleClick}>
select time
</button>
<Field
name="date"
type="date"
component={this.renderDatePicker}
label={"date"}
/>
</div>
);
}
}
export default reduxForm({
form: "simple" // a unique identifier for this form
})(SimpleForm);
这种行为的原因在于 react-form 的 Field
组件的实现。它对其所有属性进行浅层比较,以决定是否应该重新渲染。您可以随意更改组件的 state
,对 this.renderDatePicker
的引用不会更改。
Field
将包括 onChange
处理程序和当前 value
的属性传递到字段的 component
无状态函数调用中以通知更改,但这实际上并不是在此处申请,因为您的切换按钮在该字段之外。
所以我想到的一个选择是将您的按钮移动到呈现的字段中,然后调用 onChange(!value)
。
更简单但更肮脏的选择是在你的 component
属性 中使用箭头函数:component={() => this.renderDatePicker()}
- 这个实例随着你的 [=20= 的每次重新渲染而改变](即如果 state
发生变化),因此它会带来成本,但根据您应用程序的复杂性,成本可以忽略不计。为了减轻影响,您可以实现 shouldComponentUpdate
(就像 redux-form 的 Field
所做的那样)来根据当前和下一个 isOpen
状态决定是否应该重新渲染。
在 redux-form 中查看此位以获取更多详细信息:https://github.com/erikras/redux-form/blob/master/src/createField.js#L44