【问题标题】:Can I use one function for changing different states in React?我可以使用一个函数来改变 React 中的不同状态吗?
【发布时间】:2021-01-21 12:06:33
【问题描述】:

我可以传递状态并且只使用 1 个函数而不是为每个状态属性调用一个函数吗?

组件状态:

this.state =
{
  context: this.props.context,
  dataProvider: this.props.dataProvider,
  projectInformationDetails: {
    programName: "",
    projectName: "",
    projectStatus: "",
    projectStatusOptions: [],
    appStatus: "",
    appStatusOptions: [],
    governanceStatus: "",
    governanceStatusOptions: []
  },
};

输入改变时改变状态的函数:

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);
}
...

渲染中的文本组件:

<TextField
    label={strings.ProgramNameLabel}
    defaultValue={this.state.projectInformationDetails.programName}
    onChange={this.setProgramName}
/>
<TextField
     label={strings.ProjectNameLabel}
     defaultValue={this.state.projectInformationDetails.projectName}
     onChange={this.setProjectName}
/>
...

因此,我不想为每个状态使用几乎相同的函数,而只想使用一个函数:

函数(状态,值)

如果我可以访问 projectInformationDetails 的属性而不克隆所有内容,也许代码会更简洁。

例如:

this.setState( {projectInformationDetails.programName: value});

【问题讨论】:

  • 你实际上使用了 Same 函数,不清楚你在问什么,如果它的相同函数只是映射它。另外,为什么你awaitthis.setState?这不是承诺
  • 我强烈建议检查首选方式的 react hooks,并完全改变状态的处理方式

标签: javascript reactjs tsx


【解决方案1】:

如果是所有输入字段,您可以在输入标签中添加一个name 键。它看起来像&lt;input type="text" name="programName" value={programName} /&gt; 然后,名称值将对应于您尝试在状态中更改的键。

有了这个,你应该能够创建一个通用函数来设置状态值。

const onInputChange = (e) => this.setState({
  ...this.state,
  projectInformationDetails: {
    ...this.state.projectInformationDetails,
    [e.target.name]: e.target.value,
  },
});

并在输入字段的onChange上使用此功能。

我已经有一段时间没有在 React 中使用类了,所以可能需要进行一些修改。

编辑:

您可以通过在onChange 函数中添加值并通过返回另一个函数将函数用作一等公民来合并@David Barker 的部分答案。

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')}
/>

【讨论】:

  • 感谢这对我有用!我也会尝试一种不使用名称 attr 的方法。
  • @tmach 我已经编辑了我对一个示例的回复,该示例可能会按照您想要的方式工作!可能和你自己想的一样。
  • 谢谢,是的,我确实结合了你的 2 个答案。
【解决方案2】:

您可以从单个方法中组合每个事件处理程序,我不确定这样做是否会产生渲染开销,因为 React 无法跟踪事件处理程序,如果可以,您总是可以分配结果到componentDidMount中的变量。

private setComponentState(key) {
    const self = this;
    return (e) => {
        self.setState(prevState => ({
            projectInformationDetails: {
                ...prevState.projectInformationDetails,
                [key]: e.target.value,
            }
        }))
    };
}

然后每次你想和key一起使用时调用这个函数。

<TextField
    label={strings.ProgramNameLabel}
    defaultValue={this.state.projectInformationDetails.programName}
    onChange={this.setComponentState('programName')}
/>

<TextField
    label={strings.ProjectNameLabel}
    defaultValue={this.state.projectInformationDetails.projectName}
    onChange={this.setComponentState('projectName')}
/>

【讨论】:

  • 嗨,大卫,感谢您的帮助。您的代码可以工作,但我需要在最后调用另一个函数。现在有一个返回,所以它没有到达那条线。
  • 然后将函数应用到变量,调用你的函数,然后返回事件处理函数。
  • 谢谢,我合并了 2 个答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-04
  • 1970-01-01
  • 1970-01-01
  • 2022-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多