请告诉我我是否从错误的角度出发。
我有一个类组件App
,其中有许多代子组件。许多孙子组件将需要访问inventory
数据库,因此我选择使用上下文存储此数据库。
App
的构造函数的简短摘录:
constructor(props) {
super(props);
this.itemAdd=this.itemAdd.bind(this);
let tempinventory = baseinventory;
//append our itemAdd function to the context
tempinventory.itemAdd = this.itemAdd;
this.state={
inventory:tempinventory,
}
...
}
请注意,这里我要向上下文中添加函数itemAdd
,以便孙子代可以调用此函数,而无需我一直对回调进行深入研究。
一个孙子组件ItemAddForm
将需要管理一个包含多个字段的表单,并且需要在按下“提交”按钮时将表单的内容传递到itemAdd
中。我不知道如何完成此操作,因为跟踪表单的内容似乎需要ItemAddForm
是有状态的类组件,但是类组件无法在render方法之外访问Context。我知道。
这是我喜欢这样做的方式:
class ItemAddForm extends React.Component{
constructor(props){
super(props);
this.handleChange=this.handleChange.bind(this);
this.submitHandler=this.submitHandler.bind(this);
this.state = defaultstate;
}
handleChange(event) {
const name = event.target.name;
this.setState({
[name]:value,
});
}
submitHandler(event){
event.preventDefault();
let item=this.state;
this.Context.itemAdd(item);
document.getElementById("InventoryAddForm").reset();
this.setState(defaultstate);
}
render(){
return(
<div>
<form
onSubmit={this.submitHandler}
id="InventoryAddForm"
>
<input
name="price"
className="FormField"
type="text"
onChange={handleChange}
/>
...
</form>
</div>
);
}
}
但是显然这是行不通的,因为this.Context是未定义的。我是否严格需要将ItemAddForm
变成一个仅通过钩子监视表单上下文的功能组件?我应该怎么做才能做到这一点?
答案 0 :(得分:0)
修改您的代码以使用Context Consumer模式。 Context的使用者包装了一个回调,该回调使您可以访问在Context的Provider
中传递为<MyContext.Provider value={/* some value */}>
import MyContext from '../my-desired-grandparent-provider';
class ItemAddForm extends React.Component{
constructor(props){
super(props);
this.handleChange=this.handleChange.bind(this);
this.submitHandler=this.submitHandler.bind(this);
this.state = defaultstate;
this.renderContext = null;
}
handleChange(event) {
const name = event.target.name;
this.setState({
[name]:value,
});
}
submitHandler(event){
event.preventDefault();
let item=this.state;
this.renderContext.itemAdd(item);
document.getElementById("InventoryAddForm").reset();
this.setState(defaultstate);
}
renderForm = (value) => (<div>
<form
onSubmit={this.submitHandler}
id="InventoryAddForm"
>
<input
name="price"
className="FormField"
type="text"
onChange={handleChange}
/>
...
</form>
</div>)
render(){
return(
<MyContext.Consumer>
{value => {
this.renderContext = value;
return this.renderForm(value);
}}
</MyContext.Consumer>
);
}
}