访问包装HOC中的组件的功能/状态

时间:2017-12-07 15:39:21

标签: javascript reactjs

所以我有一个组件A(扩展了React.component),并用更高阶的组件B包装。

在组件B的方法中,我需要为A设置state,或者在A中调用一个函数(这样它可以执行setState) - 这通常是怎么做的?

我可以在这里粘贴实际代码,但我认为如果有处理这种情况的标准方法可能会使问题复杂化。

编辑:这里的代码 - isOpen需要更改才能关闭Modal,并且需要在handleSubmit中更改....

import React from 'react';
import Modal from 'react-modal';
import { withFormik, Form, Field } from 'formik';
import Yup from 'yup';

// first part of Formik integration
const formikEnhancer = withFormik({
  mapPropsToValues(props) {
    return {
      personName: props.email || '',
      personSurname: props.surname || '',
      personCongregation: props.congregation || ''
    }
  },
  validationSchema: Yup.object().shape({
    personName: Yup.string().required().min(1),
    personSurname: Yup.string().required().min(2),
    personCongregation: Yup.string().required().min(8)
  }),
  handleSubmit(values, {props, resetForm, setErrors, setSubmitting}) {
    submitNewPerson(values, {resetForm, setErrors, setSubmitting});
    props.testCall;
  }
});

function submitNewPerson(v, {resetForm, setErrors, setSubmitting}) {
  //e.preventDefault();

  congregations = [];
  congregations.push(v.personCongregation);

  const peep = {
    name: v.personName,
    surname: v.personSurname,
    congregations: congregations//,
    //startDate: Number(e.target.componentStartDate.value),
    //endDate: Number(e.target.componentEndDate.value)
  };
    // do the db insert here and check for errors
    setSubmitting(false);
  });
};

class AddPerson extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: undefined,
      isOpen: false
    }
  }

  componentWillMount() {
    Modal.setAppElement('body');
  }

  renderCong() {
    // this just maps out a list of select options
  }

  render() {
    return (
      <div>
        <button className="button" onClick={()=> this.setState({isOpen:true, error:undefined})}>+ Add Person</button>
        <Modal isOpen={this.state.isOpen} contentLabel="Add Person"
          className = "boxed-view__box" overlayClassName="boxed-view boxed-view--modal">
          <Form className="boxed-view__form">
            <div>
              <Field type="text" name="personName" placeholder="Name" />
            </div>
            <div>
                <Field type="text" name="personSurname" placeholder="Surname" />
            </div>
            <div>
             <Field component="select" name="personCongregation" value={this.state.cong}>
                <option key="0" value="">- Select Option -</option>
                {this.renderCong()}
              </Field>
            </div>
            <button disabled={this.props.isSubmitting} className="button">Add Person</button>
            <button disabled={this.props.isSubmitting} type="button" className="button button--secondary" onClick={
              ()=> {
                this.props.resetForm();
                this.setState({isOpen:false});
              }}>Cancel</button>
          </Form>

        </Modal>
      </div>
    )
  };
};

3 个答案:

答案 0 :(得分:4)

除非您控制组件B,否则这是不可能的。一些流行的HOC(如react-redux中的connect)有一种机制允许您公开包装的组件A,但这通常不正确。

通常最好不要这样做。如果组件的状态需要从外部更改,则应将其作为prop传递,“真实来源”应该是您的模型或视图模型。如果您使用的是redux,请尝试将组件状态移至redux状态,而不是调用setState,而是使用redux action / reducer组合来更新它。

另一种方法是将状态向上移动一级,以便它作为另一个组件(父级)的prop传入,然后在该父级中具有逻辑,尽管这不太灵活。

答案 1 :(得分:0)

通常你会向组件发送道具,然后你用一个函数处理那些道具,在这种情况下用东西设置状态,例如:

class B extends React.Component{

   render(){
       <A toUpdateState={this.state.valueB} />
   }
}

class A extends React.Component{

   updateState(){
       this.setState({
           ...this.state,
           valueA: this.props.toUpdateState
       })
   }

   render(){...}
}

如果触发B组件中的状态,A组件将收到信息。

还有其他方法可以做到这一点但没有代码很难给你一个不同的解决方案。

答案 2 :(得分:0)

想出来 - 添加了我自己的onClick处理程序(而不是允许Formik调用其handleSubmit方法) - 我的处理程序然后调用Formik的handleSubmit,然后根据返回值更改状态