我有以下结构:
FormEditor
-保存FieldEditor的多个实例FieldEditor
-编辑表单的字段,并在其状态下保存有关该字段的各种值
当单击FormEditor中的按钮时,我希望能够从所有FieldEditor
组件中收集有关字段的信息,处于其状态的信息,并将其全部包含在FormEditor中。
我考虑将有关字段的信息存储在FieldEditor
的状态之外,并将其置于FormEditor
的状态。但是,这将需要FormEditor
在其FieldEditor
组件更改并将其信息存储在其状态时侦听它们。
我不能直接进入儿童状态吗?理想吗?
现在是2020年,你们中的许多人会来到这里寻找类似的解决方案,但是有了钩子(他们很棒!)以及代码清洁度和语法方面的最新方法。
因此,正如前面的答案所述,解决这类问题的最佳方法是将状态保持在子组件field dEditor
之外。你可以用多种方式做到这一点。
最“复杂”的是一个全局上下文(状态),父级和子级都可以访问和修改它。当组件在树层次结构中非常深入时,这是一个很好的解决方案,因此在每个级别发送道具的成本很高。
在这种情况下,我认为这是不值得的,一个更简单的方法会给我们带来我们想要的结果,只是使用强大的React.useState()
。
如前所述,我们将处理更改,并将子组件的数据fieldEditor
存储在父组件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是调用时指定的值(本例中为空对象),位置1是对修改该值的函数的引用。
现在有了子组件,FieldEditor
,您甚至不需要创建带有return语句的函数。一个带有箭头函数的倾斜常数就可以了!
const FieldEditor = ({ id, value, handleChange }) => (
<div className="field-editor">
<input onChange={event => handleChange(event, id)} value={value} />
</div>
);
啊,我们完了,没什么了。只有这两个超薄的功能组件,我们的最终目标就是“访问”我们的孩子FieldEditor
值,并在我们的父母那里展示它。
您可以查看5年前被接受的答案,看看Hooks是如何使React代码变得更精简的(很多!)。
希望我的回答能帮助您学习和理解更多关于钩子的知识,如果您想查看这里的一个工作示例,请参阅。
如果您已经为各个字段编辑器有了一个onChange处理程序,我不明白为什么您不能将状态向上移动到FormEditor组件,然后从那里向字段编辑器传递一个回调来更新父状态。对我来说,这似乎是一种更有反应的方式。
大概是这样的:
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);
在我详细介绍如何访问子组件的状态之前,请务必阅读Markus ipse关于处理此特定场景的更好解决方案的回答。
如果确实希望访问组件子级的状态,可以为每个子级分配一个名为ref
的属性。现在有两种实现引用的方法:使用React.createRef()
和回调引用。
从React 16.3开始,这是目前推荐的使用参考文献的方法(有关更多信息,请参阅文档)。如果您使用的是早期版本,请参阅下面有关回调引用的内容。
您需要在父组件的构造函数中创建一个新的引用,然后通过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节点而不是组件上使用这些引用(例如
此属性接受一个回调函数,该函数传递对附加组件的引用。此回调在装入或卸下组件后立即执行。
例如:
<FieldEditor
ref={(fieldEditor1) => {this.fieldEditor1 = fieldEditor1;}
{...props}
/>
在这些示例中,引用存储在父组件上。要在代码中调用此组件,可以使用:
this.fieldEditor1
然后使用
this.fieldEditor1.state
获取状态。
需要注意的一点是,在尝试访问子组件之前,请确保其已渲染^_^
如上所述,如果在DOM节点而不是组件上使用这些引用(例如
如果您想了解更多关于React的ref属性的信息,请从Facebook查看此页面。
确保您阅读了“不要过度使用引用”部分,该部分指出您不应该使用孩子的
状态来“使事情发生”。
问题内容: 我有以下结构: -包含多个FieldEditor- 编辑表单的字段并在其状态下保存有关该字段的各种值 在FormEditor中单击按钮时,我希望能够从所有组件中收集有关字段的信息,处于其状态的信息,并将其全部包含在FormEditor中。 我考虑过将有关字段信息的信息存储在的状态之外,而是将其置于的状态。但是,这将需要在组件的每个组件发生更改时侦听它们并以其状态存储其信息。 我不能只访
问题内容: 我只是做一个简单的应用程序来学习与redux异步。我已经使所有工作正常进行,现在我只想在网页上显示实际状态。现在,我实际上如何在render方法中访问商店的状态? 这是我的代码(所有内容都在一页中,因为我只是在学习): 因此,在状态的render方法中,我想列出商店中的所有内容。 谢谢 问题答案: 您应该创建单独的组件,该组件将侦听状态更改并在每次状态更改时进行更新:
我只是做了一个简单的应用程序学习异步与Redux。我已经使所有的工作,现在我只想显示的实际状态到网页上。现在,我如何在render方法中实际访问存储的状态? 这里是我的代码(所有内容都在一个页面中,因为我只是在学习): 谢谢
我在react native中有一个搜索栏组件,它在父组件中导入, SearchBar子组件具有以下元素: 是否可以访问此子组件在其中导入的父组件中的状态?提前感谢你的帮助
我还没有反应过来,现在我的状态中有了这些信息(如图所示),我如何才能访问消息:? 我尝试了和,但似乎两者都不对,有人能告诉我如何访问消息吗?非常感谢。 //////////////////////////////////////////// 嗨,克里斯,非常感谢你的回答。 您是对的,错误对象是从API返回的,我已经将其添加到状态。 我也试过 this.set状态({错误: errorObjFrom
我想访问