In my code, was trying to render a <DatePicker>
in <Field>
component of Redux Form, via a function called renderDatePicker()
. This function is linked to handleClick()
function where the state variable isOpen
is set to true
.
So ideally, onClick
should render the <DatePicker>
as it is set to visible. But code doesn't update anything. Where am I doing wrong here?
Note: Rendering <DatePicker>
alone directly without the help of <Field component=...>
, works fine.
For debugging, complete code is in 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);
The reason for this behavior lies in the implementation of react-form's Field
component. It does a shallow compare of all its properties to decide whether it should rerender. You can change your component's state
as much as you like, the reference to this.renderDatePicker
won't change.
Field
passes properties including an onChange
handler and the current value
into the field's component
stateless function call to notify of changes, but this doesn't really apply here because your toggle button is outside of the field.
So one option that comes to my mind is to move your button into the rendered field and then call onChange(!value)
.
The easier yet dirtier option would be to use an arrow function in your component
property: component={() => this.renderDatePicker()}
- this instance changes with every re-render of your SimpleForm
(ie if the state
changes), so it comes with a cost, but depending on the complexity of your application the cost is negligible. To mitigate the impact, you could implement shouldComponentUpdate
(just like redux-form's Field
does) to decide whether it should rerender or not, based on the current and next isOpen
state.
Check this bit in redux-form for more details: https://github.com/erikras/redux-form/blob/master/src/createField.js#L44
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.