Reputation: 447
I'm building a complex form in React and am trying to use Redux Forms as a helper tool.
The requirements of the project are that:
There will be values on the page that change depending on the input fields (like an excel spreadsheet)
There will be at least one field that functions both as an input field and a dependent field (it can be changed, but also changes when other fields are changed)
I want to control when the state changes. By default, it will happen instantly when inputs change, but I'd rather have a delay like this example.
The first function basically follows the tutorial of Redux Forms, I have that working. However, the other two require modifying what happens when a field updates and I am having trouble figuring out how to do that. I could imagine how to do this from scratch, but wanted to see if there was a way to use this library to keep things simpler.
My code is up on GitHub (side question, does anyone have insight why my GitHub pages site gives a 404?
Upvotes: 1
Views: 3125
Reputation: 4734
You would have to create a custom component to place inside of redux-form's Field
, in which you hold an internal state, and sync this with the formReducer
whenever you want.
You can achieve this in a couple of steps:
Create a custom component to use inside of Field
. This component is injected with a meta
and input
prop.
Create your state
for your React Component in which you will keep track of the data that you'll eventually emit to the formReducer.
In your constructor, use props.input.value
to set your initial state. If you do this, you can use the 'initialValues' object for your reduxForm
.
Use connect
by react-redux
to make it possible to use react-form
's action creators. In your case you'll be using the change
action creator.
Create your render function with your input-field and fire the change
action to modify your formReducer's value for this field.
So that comes down to something like this:
<Field
name="daysPerWeek"
component={MyCustomComponent} // 1
/>
...
class MyCustomComponent {
constructor(props) {
super(props);
this.state = {
value: props.input.value, // 2 and 3
}
}
....
}
4:
import { connect } from 'react-redux';
import { change } from 'react-form';
const mapDispatchToProps = (dispatch, ownProps) => ({
ourCustomChange: (value) => dispatch(change(ownProps.meta.form, ownProps.input.name, value))
})
export default connect(undefined, mapDispatchToProps)(MyCustomComponent);
5:
....
componentDidUpdate(prevProps, prevState) {
if (prevState.value !== this.state.value) {
this.debounceAndEmit();
}
}
debounceAndEmit() {
// Debounce for some time. Maybe use:
// import { debounce } from 'throttle-debounce';
// for that:
debounce(2000, () => {
this.props.ourCustomChange(this.state.value)
})
}
handleChange(event) {
// Do things here like trimming the string, regex, whatever.
this.setState({ value: event.target.value })
}
render() {
return (
<input
{...this.props.input} // Includes standard redux-form bindings for input fields.
value={this.state.value}
onChange={this.handleChange.bind(this)}
/>
)
}
....
In some cases you might have to use the blur action creator too. For when you're doing stuff when clicking outside of an input field for example.
If you want form fields to change depending on other fields, you should use selectors to inject their values into your custom component to respond to that.
Does this answer your question?
Upvotes: 1