如何在React中访问孩子的状态?

我有以下结构:

FormEditor-包含多个FieldEditor- FieldEditor编辑表单的字段并在其状态下保存有关该字段的各种值

在FormEditor中单击按钮时,我希望能够从所有FieldEditor组件中收集有关字段的信息,处于其状态的信息,并将其全部包含在FormEditor中。

我考虑过将有关字段信息的信息存储在FieldEditor的状态之外,而将其置于FormEditor的状态。但是,这将需要FormEditorFieldEditor组件的每个组件发生更改时侦听它们并以其状态存储其信息。

我不能只访问儿童的州吗?理想吗?

老丝Jim猴子2020/03/10 22:26:28

它的2020年以及许多人将来到这里寻找类似的解决方案,但要使用Hooks(它们很棒!),并提供有关代码整洁度和语法的最新方法。

因此,如先前的回答所述,解决此类问题的最佳方法是将状态保持在子组件之外fieldEditor您可以通过多种方式做到这一点。

最“复杂”的是具有父级和子级都可以访问和修改的全局上下文(状态)。当组件在树层次结构中很深时,​​这是一个很好的解决方案,因此在每个级别发送道具的成本很高。

在这种情况下,我认为这样做不值得,仅使用功能强大的,更简单的方法即可为我们带来所需的结果React.useState()

使用React.useState()钩子的方法,比使用Class组件更简单

如前所述,我们将处理更改并将子组件的数据存储fieldEditor在父组件fieldForm为此,我们将发送一个引用,该引用将处理并将更改应用于fieldForm状态,您可以使用以下方法进行操作:

function FieldForm({ fields }) {
  const [fieldsValues, setFieldsValues] = React.useState({});
  const handleChange = (event, fieldId) => {
    let newFields = { ...fieldsValues };
    newFields[fieldId] = event.target.value;

    setFieldsValues(newFields);
  };

  return (
    <div>
      {fields.map(field => (
        <FieldEditor
          key={field}
          id={field}
          handleChange={handleChange}
          value={fieldsValues[field]}
        />
      ))}
      <div>{JSON.stringify(fieldsValues)}</div>
    </div>
  );
}

请注意,这React.useState({})将返回一个数组,其中位置0是调用时指定的值(在这种情况下为Empty对象),位置1是对修改该值的函数的引用。

现在有了子组件,FieldEditor您甚至不需要创建带有return语句的函数,带有箭头函数的精益常量就可以了!

const FieldEditor = ({ id, value, handleChange }) => (
  <div className="field-editor">
    <input onChange={event => handleChange(event, id)} value={value} />
  </div>
);

Aaaaand we are done, nothing more, with just these two slime functional components we have our end goal "access" our child FieldEditor value and show it off in our parent.

You could check the accepted answer from 5 years ago and see how Hooks made React code leaner (By a lot!).

Hope my answer helps you learn and understand more about Hooks, and if you want to check a working example here it is.

樱斯丁2020/03/10 22:26:28

现在,您可以访问InputField的状态,该状态是FormEditor的子级。

基本上,只要输入字段(子级)的状态发生变化,我们就从事件对象获取值,然后将该值传递给父级,并在父级中设置状态。

在按钮上单击,我们只是打印输入字段的状态。

这里的关键点是,我们在生成可重用的子输入字段时,使用道具获取输入字段的ID /值,并调用在输入字段上设置为属性的函数。

class InputField extends React.Component{
  handleChange = (event)=> {
    const val = event.target.value;
    this.props.onChange(this.props.id , val);
  }

  render() {
    return(
      <div>
        <input type="text" onChange={this.handleChange} value={this.props.value}/>
        <br/><br/>
      </div>
    );
  }
}       


class FormEditorParent extends React.Component {
  state = {};
  handleFieldChange = (inputFieldId , inputFieldValue) => {
    this.setState({[inputFieldId]:inputFieldValue});
  }
  //on Button click simply get the state of the input field
  handleClick = ()=>{
    console.log(JSON.stringify(this.state));
  }

  render() {
    const fields = this.props.fields.map(field => (
      <InputField
        key={field}
        id={field}
        onChange={this.handleFieldChange}
        value={this.state[field]}
      />
    ));

    return (
      <div>
        <div>
          <button onClick={this.handleClick}>Click Me</button>
        </div>
        <div>
          {fields}
        </div>
      </div>
    );
  }
}

const App = () => {
  const fields = ["field1", "field2", "anotherField"];
  return <FormEditorParent fields={fields} />;
};

ReactDOM.render(<App/>, mountNode);