我有以下结构:
FormEditor
-保存FieldEditor FieldEditor
的多个实例-编辑表单的字段,并在其状态下保存有关该字段的各种值
当在FormEditor中单击一个按钮时,我希望能够从所有FieldEditor
组件收集有关字段的信息、处于其状态的信息,并将其全部放在FormEditor中。
我考虑将关于字段的信息存储在FieldEditor
的状态之外,并将其置于FormEditor
的状态中,然而,这将需要FormEditor
在每个FieldEditor
组件发生变化时监听它们,并将它们的信息存储在其状态中。
我不能直接访问孩子的状态吗?它是理想的吗?
发布于 2015-01-10 18:11:17
如果您已经有了单个FieldEditors的onChange处理程序,我不明白为什么您不能将状态向上移动到FormEditor组件,然后从那里向下传递一个将更新父状态的FieldEditors回调。对我来说,这似乎是一种更具反应性的方式。
大概是这样的:
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);
发布于 2015-03-27 22:39:07
在我详细介绍如何访问子组件的状态之前,请务必阅读Markus-ipse关于处理此特定场景的更好解决方案的答案。
如果您确实希望访问组件的子项的状态,则可以为每个子项分配一个名为ref
的属性。现在有两种方法来实现引用:使用React.createRef()
和回调引用。
使用React.createRef()
从React 16.3开始,这是目前推荐的使用引用的方式(有关更多信息,请参阅the documentation )。如果您使用的是较早的版本,请参阅下面有关回调引用的内容。
您需要在父组件的构造函数中创建一个新的引用,然后通过ref
属性将其分配给子组件。
class FormEditor extends React.Component {
constructor(props) {
super(props);
this.FieldEditor1 = React.createRef();
}
render() {
return <FieldEditor ref={this.FieldEditor1} />;
}
}
为了访问这种ref,您需要使用:
const currentFieldEditor1 = this.FieldEditor1.current;
这将返回已挂载组件的一个实例,这样您就可以使用currentFieldEditor1.state
访问该状态。
简单地说,如果您在DOM节点而不是组件(例如<div ref={this.divRef} />
)上使用这些引用,那么this.divRef.current
将返回底层DOM元素而不是组件实例。
回调引用
此属性接受一个回调函数,该函数被传递一个对附加组件的引用。此回调在组件挂载或卸载后立即执行。
例如:
<FieldEditor
ref={(fieldEditor1) => {this.fieldEditor1 = fieldEditor1;}
{...props}
/>
在这些示例中,引用存储在父组件上。要在代码中调用此组件,可以使用:
this.fieldEditor1
然后使用this.fieldEditor1.state
获取状态。
需要注意的一件事是,在尝试访问^_^之前,请确保子组件已经呈现
如上所述,如果您在DOM节点而不是组件(例如<div ref={(divRef) => {this.myDiv = divRef;}} />
)上使用这些引用,那么this.divRef
将返回底层DOM元素而不是组件实例。
更多信息
如果你想了解有关React的ref属性的更多信息,请查看Facebook上的this page。
确保你阅读了"Don't Overuse Refs“一节,其中说你不应该使用孩子的state
来”让事情发生“。
发布于 2021-12-22 02:01:14
您可以通过向子组件传递回调来访问子状态。
const Parent = () => {
return (
<Child onSubmit={(arg) => {
console.log('accessing child state from parent callback: ', arg)
}}
/>
)
}
const Child = ({onSubmit}) => {
const [text, setText] = useState('');
return (
<>
<input value={text} onChange={setText}>
<button onClick={() => onSubmit(search)} />
</>
)
}
现在,如果单击子组件中的按钮,您将执行从父组件传递的函数,并可以访问子组件的状态变量。
https://stackoverflow.com/questions/27864951
复制相似问题