Reputation: 18694
I call an API, get a payload and load it into state. Eg:
Payload : {
id: 1,
firstName: 'Craig',
surname: 'Smith',
anotherField: 'test data',
....
}
(Note, there are around 20 fields in real life)
On my react screen, I have the fields to display this data. At the moment, for every field, I have an onChange function. So:
this.firstnameOnChange = this.firstnameOnChange.bind(this);
and then the function:
firstnameOnChange() { ....}
Is there a simpler pattern to maybe lessen the amount of methods I need to create? Some sort of generic OnChange event that takes a name, and the value, which can then be used to update the state?
I can bind to something like:
myOnChange(fieldName, value) {
// Somehow find the 'fieldName' in the state and update it's value with 'value'
}
Is this a valid pattern? Or is there a better way? Or should I stick to separate OnChange methods for each field?
If I can go generic, how would I find the name of the field in the state to update?
Upvotes: 1
Views: 464
Reputation: 1892
Since the state is an object that means you can update it's key and value. All you have to do is pass down the correct parameters to a generic update function which will update the state.
Here's one way you can do it: https://codesandbox.io/s/v382v6l483
Since your payload is an entry one level down, we'll be using the spread operator and spread out the payload object.
Update the value that you need and finally returns the payload to setState
function to update the state and rerender the component.
You can bind this function to each field and keep your state updated.
Read more here on handling events and binding functions: https://reactjs.org/docs/handling-events.html
Upvotes: 1
Reputation: 8102
No this is not recommended to write onChange
for every field. You can write a generic onChange method like this:
handleChange= name => event => {
this.setState({payload: {...this.state.payload, [name] : event.target.value}});
}
for example you have an input like this :
<Input onChange={this.handleChange('firstName')} placeholder="Please Enter" />
PS here we are invoking handleChange directly so we use currying
means a new instance being created for every invocation. There is another approach by extract name
form event.target
and create a name
attribute in your input. Then you don't need to pass input name explicitly.
Upvotes: 4