小编典典

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

all

我有以下结构:

FormEditor- 拥有 FieldEditor 的多个实例 FieldEditor- 编辑表单的字段并在其状态下保存有关它的各种值

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

我考虑将有关字段的信息存储在FieldEditor‘ 状态之外,并将其置于FormEditor
状态。但是,这将需要在其每个组件更改FormEditor时监听其每个FieldEditor组件并将其信息存储在其状态中。

我不能只访问孩子的状态吗?理想吗?


阅读 74

收藏
2022-04-26

共1个答案

小编典典

如果您已经为各个 FieldEditor 提供了 onChange 处理程序,我不明白为什么您不能将状态向上移动到 FormEditor
组件,然后将回调从那里传递给将更新父状态的 FieldEditor。对我来说,这似乎是一种更 React-y 的方式。

可能是这样的:

const FieldEditor = ({ value, onChange, id }) => {
  const handleChange = event => {
    const text = event.target.value;
    onChange(id, text);
  };

  return (
    <div className="field-editor">
      <input onChange={handleChange} value={value} />
    </div>
  );
};

const FormEditor = props => {
  const [values, setValues] = useState({});
  const handleFieldChange = (fieldId, value) => {
    setValues({ ...values, [fieldId]: value });
  };

  const fields = props.fields.map(field => (
    <FieldEditor
      key={field}
      id={field}
      onChange={handleFieldChange}
      value={values[field]}
    />
  ));

  return (
    <div>
      {fields}
      <pre>{JSON.stringify(values, null, 2)}</pre>
    </div>
  );
};

// To add the ability to dynamically add/remove fields, keep the list in state
const App = () => {
  const fields = ["field1", "field2", "anotherField"];

  return <FormEditor fields={fields} />;
};

原始 - 挂钩前版本:

class FieldEditor extends React.Component {
  constructor(props) {
    super(props);
    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    const text = event.target.value;
    this.props.onChange(this.props.id, text);
  }

  render() {
    return (
      <div className="field-editor">
        <input onChange={this.handleChange} value={this.props.value} />
      </div>
    );
  }
}

class FormEditor extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};

    this.handleFieldChange = this.handleFieldChange.bind(this);
  }

  handleFieldChange(fieldId, value) {
    this.setState({ [fieldId]: value });
  }

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

    return (
      <div>
        {fields}
        <div>{JSON.stringify(this.state)}</div>
      </div>
    );
  }
}

// Convert to a class component and add the ability to dynamically add/remove fields by having it in state
const App = () => {
  const fields = ["field1", "field2", "anotherField"];

  return <FormEditor fields={fields} />;
};

ReactDOM.render(<App />, document.body);
2022-04-26