Reactjs:如何从submitHandler访问上下文?

时间:2019-08-24 19:30:16

标签: reactjs forms callback react-hooks react-context

请告诉我我是否从错误的角度出发。

我有一个类组件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变成一个仅通过钩子监视表单上下文的功能组件?我应该怎么做才能做到这一点?

1 个答案:

答案 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>
    );
  }
}