如何在 React 中访问孩子的状态 [英] How to access a child's state in React

查看:32
本文介绍了如何在 React 中访问孩子的状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下结构:

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

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

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

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

解决方案

如果您已经有用于各个 FieldEditor 的 onChange 处理程序,我不明白为什么您不能将状态向上移动到 FormEditor 组件并直接通过从那里向下回调到将更新父状态的 FieldEditors.对我来说,这似乎是一种更符合 React 的方式.

大概是这样的:

const FieldEditor = ({ value, onChange, id }) =>{const handleChange = 事件 =>{const text = event.target.value;onChange(id, text);};返回 (<div className="field-editor"><input onChange={handleChange} value={value}/>

);};const FormEditor = props =>{const [values, setValues] = useState({});const handleFieldChange = (fieldId, value) =>{setValues({ ...values, [fieldId]: value });};const fields = props.fields.map(field => (<现场编辑器键={字段}id={字段}onChange={handleFieldChange}值={值[字段]}/>));返回 (<div>{字段}<pre>{JSON.stringify(values, null, 2)}</pre>

);};//要添加动态添加/删除字段的能力,请保持列表处于状态const App = () =>{const fields = [field1", field2", anotherField"];return <FormEditor fields={fields}/>;};

原始 - 预挂钩版本:

class FieldEditor extends React.Component {构造函数(道具){超级(道具);this.handleChange = this.handleChange.bind(this);}句柄变化(事件){const text = event.target.value;this.props.onChange(this.props.id, text);}使成为() {返回 (<div className="字段编辑器"><input onChange={this.handleChange} value={this.props.value}/>

);}}类 FormEditor 扩展了 React.Component {构造函数(道具){超级(道具);this.state = {};this.handleFieldChange = this.handleFieldChange.bind(this);}handleFieldChange(fieldId, value) {this.setState({ [fieldId]: value });}使成为() {const fields = this.props.fields.map(field => (<现场编辑器键={字段}id={字段}onChange={this.handleFieldChange}值={this.state[field]}/>));返回 (<div>{字段}<div>{JSON.stringify(this.state)}</div>

);}}//转换为类组件并通过使其处于状态来添加动态添加/删除字段的能力const App = () =>{const fields = ["field1", "field2", "anotherField"];return <FormEditor fields={fields}/>;};ReactDOM.render(, document.body);

I have the following structure:

FormEditor - holds multiple instances of FieldEditor FieldEditor - edits a field of the form and saving various values about it in its state

When a button is clicked within FormEditor, I want to be able to collect information about the fields from all FieldEditor components, information that's in their state, and have it all within FormEditor.

I considered storing the information about the fields outside of FieldEditor's state and put it in FormEditor's state instead. However, that would require FormEditor to listen to each of its FieldEditor components as they change and store their information in its state.

Can't I just access the children's state instead? Is it ideal?

解决方案

If you already have an onChange handler for the individual FieldEditors I don't see why you couldn't just move the state up to the FormEditor component and just pass down a callback from there to the FieldEditors that will update the parent state. That seems like a more React-y way to do it, to me.

Something along the line of this perhaps:

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} />;
};

Original - pre-hooks version:

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

这篇关于如何在 React 中访问孩子的状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆