Can I pass the state and only use 1 function instead of calling a function for every state property?
Component state:
this.state =
{
context: this.props.context,
dataProvider: this.props.dataProvider,
projectInformationDetails: {
programName: "",
projectName: "",
projectStatus: "",
projectStatusOptions: [],
appStatus: "",
appStatusOptions: [],
governanceStatus: "",
governanceStatusOptions: []
},
};
Function for changing state when input changes:
private async setProgramName(e) {
await this.setState(prevState => ({
projectInformationDetails: {
...prevState.projectInformationDetails,
programName: e.target.value,
}
}));
this.props.updateProjectItem(this.state.projectInformationDetails);
}
private async setProjectName(e) {
await this.setState(prevState => ({
projectInformationDetails: {
...prevState.projectInformationDetails,
projectName: e.target.value,
}
}));
this.props.updateProjectItem(this.state.projectInformationDetails);
}
...
Text Component in render:
<TextField
label={strings.ProgramNameLabel}
defaultValue={this.state.projectInformationDetails.programName}
onChange={this.setProgramName}
/>
<TextField
label={strings.ProjectNameLabel}
defaultValue={this.state.projectInformationDetails.projectName}
onChange={this.setProjectName}
/>
...
So instead of using almost the same function for every state, I just want to use one single function:
func(state, value)
Maybe the code will be cleaner if I can access the property of projectInformationDetails without cloning everything back.
For example:
this.setState( {projectInformationDetails.programName: value});
If it is all input fields, you could add a name
key to the input tag. It would look something like <input type="text" name="programName" value={programName} />
The name value would then correspond to key that you're trying to change in the state.
With this you should be able to create a generic function to set the state value.
const onInputChange = (e) => this.setState({
...this.state,
projectInformationDetails: {
...this.state.projectInformationDetails,
[e.target.name]: e.target.value,
},
});
And use this function on the input field's onChange
.
I haven't used classes with React in a while, so there is probably some modification that needs to be done.
Edit:
You could incorporate part of @David Barker's answer by adding the value in the onChange
function and using functions as first class citizens, by returning another function.
const onChange = (property) => (e) => this.setState({
...this.state,
projectInformationDetails: {
...this.state.projectInformationDetails,
[property]: e.target.value,
},
});
...
<TextField
label={strings.ProjectNameLabel}
defaultValue={this.state.projectInformationDetails.projectName}
onChange={onChange('programName')}
/>