Access state of parent component in a child component?

被刻印的时光 ゝ 提交于 2019-12-08 13:52:45

问题


I'm new to react js and I need to get the state of the component to be accessed by another class, I encountered this problem because I'm using atomic design because writing everything in one component is turning to be a problem, here is my code: Headcomponent:

class Headcomponent extends React.Component{

  constructor (props) {

    super(props);
    this.state = {
      email: '',
      password: '',
      formErrors: {email: '', password: ''},
      emailValid: false,
      passwordValid: false,
      formValid: false,
      items: [],

    }
  }


    this.setState({formErrors: fieldValidationErrors,
                    emailValid: emailValid,
                    passwordValid: passwordValid
                  }, this.validateForm);
}

validateForm() {
  this.setState({formValid: this.state.emailValid && 
  this.state.passwordValid});
}


render(){
        return (
  <Form fields={this.props.form} buttonText="Submit" />
        );
    }
}


Headcomponent.propTypes = {
  form: PropTypes.array,
};

Headcomponent.defaultProps = {
  form: [
    {
      label: 'label1',
      placeholder: 'Input 1',
    },
    {
      label: 'label2',
      placeholder: 'Placeholder for Input 2',
    },
  ],
};

export default Headcomponent;

form.js

   const Form = props => (
      <form className="Form">
        {
          props.fields.map((field, i) => (<LabeledInput label={field.label} placeholder={field.placeholder} key={i}/>))
        }
        <Button text={props.buttonText} />
      </form>
    );

    Form.propTypes = {
      fields: PropTypes.arrayOf(PropTypes.object).isRequired,
      buttonText: PropTypes.string.isRequired,
    };

    export default Form;

LabeledInput.js (where I need to pass the state of my password)

const LabeledInput = props => (
  <div className={`form-group `} >
    <Label text={props.label} />
    <Input value={props.value} placeholder={props.placeholder} type="text" onChange={props.onChange} />
    <div class="valid-feedback">{props.errorMessage}</div>
    <small class="form-text text-muted">{props.exampleText}</small>
  </div>
);

LabeledInput.propTypes = {
  label: PropTypes.string.isRequired,
  placeholder: PropTypes.string,
  onChange: PropTypes.func.required,
  value: PropTypes.string.isRequired,
  exampleText: PropTypes.string,
  errorMessage: PropTypes.string,
};

export default LabeledInput;

How can I access state of headComponent in LabeledInput?


回答1:


The simplest way to access the state of headComponent in LabeledInput in to keep passing it down.

If you want to access the value this.state.password from headComponent inside LabeledInput then you pass this this.state.password as a prop to the form component in the render method

   render(){
        return (
          <Form 
            fields={this.props.form} 
            buttonText="Submit" 
            password={this.state.password} />
        );
    }

This then gives you access to this.state.password as a prop inside the Form component. You then repeat the process and pass it to the LabeledInput component inside form

const Form = props => (
      <form className="Form">
        {
          props.fields.map((field, i) => (
            <LabeledInput 
                label={field.label} 
                placeholder={field.placeholder} 
                key={i}
                password={this.props.password}
             />))
        }
        <Button text={props.buttonText} />
      </form>
    );

This then gives you access to the value inside the LabeledInput component by calling this.props.password.




回答2:


The most reasonable way is passing it down (The values of Headcomponent's state you need) as props:

Headcomponent.js

class Headcomponent extends React.Component {
  constructor (props) {
    super(props);

    this.state = {
      email: '',
      password: '',
      formErrors: {email: '', password: ''},
      emailValid: false,
      passwordValid: false,
      formValid: false,
      items: [],
    }
  }

  render() {
    return (
      <Form
        fields={this.props.form}
        formValid={this.state.formValid}  // from Headcomponent's state
        buttonText="Submit"
      />
    );
  }
}

Form.js

const Form = props => (
   <form className="Form">
     {
       props.fields.map((field, i) => (
         <LabeledInput
           label={field.label}
           formValid={props.formValid}  // from Headcomponent's state
           placeholder={field.placeholder}
           key={i}
         />
       ))
     }
     <Button text={props.buttonText} />
   </form>
 );

LabeledInput.js

 const LabeledInput = props => (
   <div className={`form-group `} >
     { props.formValid && 'This form is valid' }  // from Headcomponent's state
     <Label text={props.label} />
     <Input value={props.value} placeholder={props.placeholder} type="text" onChange={props.onChange} />
     <div class="valid-feedback">{props.errorMessage}</div>
     <small class="form-text text-muted">{props.exampleText}</small>
   </div>
 );

So if any time the Headcomponent's state is updated it will be propagated to the LabeledInput component




回答3:


You can use props to achieve this.

Root Component:

<div>
  <child myState="hello"></child>
</div>

Child Component:

<div>
  <child2 myOtherProperty={this.props.myState}></child2>
</div>

Child1 Component:

<div>{this.props.myOtherProperty}</div>

You can also pass functions as property to other components and let them call back the the root component if needed like so:

<div>
  <child onChange={this.myOnChangeMethodDefinedInRootComponent.bind(this)}></child>
</div>

this way you can "tell" the root components if something changed inside the children without using Redux

hope this helps




回答4:


Here is a quick prototype of what you are looking at,

passing state from head component as props to all the way down to label compoent. Changes in label component will modify the state of head component and force to re-render all components.

// Head Component
class HeadCompoent {
  constructor() {
    this.state = {
      password: '',
      userName: '',
    }
  }

  handleFieldChange = (key, val) => {
    this.setState({
      [key]: val,
    });
  };

  render() {
    <Form
      fields={[{
        item: {
          value: this.state.password,
          type: 'password',
          key: 'password'
        },
      }, {
        item: {
          value: this.state.userName,
          type: 'text',
          key: 'userName'
        }
      }]}
      handleFieldChange={this.handleFieldChange} 
    />
  }
}

// Form Component
const Form = (fields) => (
  <div>
    {
      fields.map(p => <Label {...p} />)
    }
  </div>);


// Label Component
const Label = ({ type, value, key, handleFieldChange }) => {
  const handleChange = (key) => (e) => {
    handleFieldChange(key, e.target.value);
  };

  return (
    <input type={type} value={value} key={key} onChange={handleChange(key)} />
  );
};



回答5:


export default headComponent then import it inside LabelledInout

This is the Headcomponent

export default class Headcomponent extends React.Component{ 
  ...
}

LabelledInput Component

 import Headcomponet from './headComponent.js'

 const LabelledInput = (props) => {
    return(<Headcomponent />);
 }


来源:https://stackoverflow.com/questions/48662186/access-state-of-parent-component-in-a-child-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!