Javascript 如何访问孩子';反应中的状态

Javascript 如何访问孩子';反应中的状态,javascript,reactjs,Javascript,Reactjs,我的结构如下: FormEditor-保存FieldEditor的多个实例 FieldEditor-编辑表单的字段,并在其状态下保存有关该字段的各种值 当在FormEditor中单击一个按钮时,我希望能够从所有FieldEditor组件中收集有关字段的信息、处于其状态的信息,并将其全部保存在FormEditor中 我考虑将有关字段的信息存储在FieldEditor的状态之外,并将其置于FormEditor的状态。但是,这将需要FormEditor在其FieldEditor组件更改并将其信息存储在

我的结构如下:

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

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

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


我不能直接进入儿童状态吗?理想吗?

如果您已经为各个FieldEditor设置了onChange处理程序,我不明白为什么您不能将状态向上移动到FormEditor组件,然后将回调传递到FieldEditor,以更新父状态。对我来说,这似乎是一种更具反应性的方式

大概是这样的:

constfieldeditor=({value,onChange,id})=>{
const handleChange=事件=>{
常量文本=event.target.value;
onChange(id,text);
};
返回(
);
};
const FormEditor=props=>{
const[values,setValues]=useState({});
常量handleFieldChange=(字段ID,值)=>{
setValues({…values,[fieldId]:value});
};
常量字段=props.fields.map(字段=>(
));
返回(
{fields}
class FormEditor extends React.Component {
  constructor(props) {
    super(props);
    this.FieldEditor1 = React.createRef();
  }
  render() {
    return <FieldEditor ref={this.FieldEditor1} />;
  }
}
{JSON.stringify(值,null,2)} ); }; //要添加动态添加/删除字段的功能,请保持列表处于状态 常量应用=()=>{ 常量字段=[“字段1”、“字段2”、“其他字段”]; 返回; };
原件-预安装版本:

类字段编辑器扩展了React.Component{
建造师(道具){
超级(道具);
this.handleChange=this.handleChange.bind(this);
}
手变(活动){
常量文本=event.target.value;
this.props.onChange(this.props.id,text);
}
render(){
返回(
);
}
}
类FormEditor扩展了React.Component{
建造师(道具){
超级(道具);
this.state={};
this.handleFieldChange=this.handleFieldChange.bind(this);
}
handleFieldChange(字段ID,值){
this.setState({[fieldId]:value});
}
render(){
const fields=this.props.fields.map(field=>(
));
返回(
{fields}
class FormEditor extends React.Component {
  constructor(props) {
    super(props);
    this.FieldEditor1 = React.createRef();
  }
  render() {
    return <FieldEditor ref={this.FieldEditor1} />;
  }
}
{JSON.stringify(this.state)} ); } } //转换为类组件,并通过使其处于状态来添加动态添加/删除字段的功能 常量应用=()=>{ 常量字段=[“字段1”、“字段2”、“其他字段”]; 返回; };
render(,document.body)在我详细介绍如何访问子组件的状态之前,请务必阅读您的答案,了解如何更好地处理此特定场景

如果确实希望访问组件子级的状态,可以为每个子级分配一个名为
ref
的属性。现在有两种实现引用的方法:使用
React.createRef()
和回调引用

使用
React.createRef()
从React 16.3开始,这是目前推荐的使用参考文献的方法(有关更多信息,请参阅)。如果您使用的是早期版本,请参阅下面有关回调引用的内容

您需要在父组件的构造函数中创建一个新引用,然后通过
ref
属性将其分配给子组件

const currentFieldEditor1 = this.FieldEditor1.current;
这将返回已安装组件的实例,因此您可以使用
currentFieldEditor1.state
访问该状态

请注意,如果在DOM节点而不是组件(例如
)上使用这些引用,则
this.divRef.current
将返回底层DOM元素,而不是组件实例

回调引用 此属性接受一个回调函数,该函数传递对附加组件的引用。此回调在装入或卸下组件后立即执行

例如:

this.fieldEditor1
然后使用
this.fieldEditor1.state
获取状态

需要注意的一点是,在尝试访问子组件之前,请确保其已渲染^_^

如上所述,如果在DOM节点而不是组件上使用这些引用(例如,
{this.myDiv=divRef;}}}/>
),则
this.divRef
将返回底层DOM元素,而不是组件实例

进一步资料 如果您想了解更多关于React的ref属性的信息,请访问Facebook


确保您阅读了“”部分,该部分说明您不应使用子项的
状态来“使事情发生”。

现在您可以访问输入字段的状态,它是FormEditor的子项

基本上,每当输入字段(子字段)的状态发生变化时,我们都会从事件对象获取值,然后将该值传递给父字段,在父字段中设置状态

单击一个按钮,我们只是打印输入字段的状态

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

类InputField扩展了React.Component{
handleChange=(事件)=>{
const val=event.target.value;
this.props.onChange(this.props.id,val);
}
render(){
返回(


); } } 类FormEditorParent扩展了React.Component{ 状态={}; handleFieldChange=(inputFieldId,inputFieldValue)=>{ this.setState({[inputField
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 a 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);
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>
  );
}
const FieldEditor = ({ id, value, handleChange }) => (
  <div className="field-editor">
    <input onChange={event => handleChange(event, id)} value={value} />
  </div>
);
const Parent = () => {
    const myRef = useRef();
    return <Child ref={myRef} />;
}

const Child = React.forwardRef((props, ref) => {
    const [myState, setMyState] = useState('This is my state!');
    useImperativeHandle(ref, () => ({getMyState: () => {return myState}}), [myState]);
})