Melissa94
Melissa94

Reputation: 423

React: Get state of children component component in parent

I have this container where and is not placed in the same level. How can I get the state of the Form when I click on the button (which is placed on the parent) ?

I've created a demo to address my issue.

https://codesandbox.io/s/kmqw47p8x7

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

  save = () => {
    alert("how to get state of Form?");
    //fire api call
  };
  render() {
    return (
      <div>
        <Form />
        <button onClick={this.save}>save</button>
      </div>
    );
  }
}

Upvotes: 0

Views: 7720

Answers (4)

Estus Flask
Estus Flask

Reputation: 223074

As it was mentioned, a ref can be used to get stateful component instance and access the state, but this breaks encapsulation:

<Form ref={this.formRef}/>

A more preferable way is to refactor Form to handle this case, i.e. accept onChange callback prop that would be triggered on form state changes:

<Form onChange={this.onFormChange}/>

One thing I don't want to do is sync the state for onChange event, because within Form there might be another Form.

Forms will need to handle this any way; it would be impossible to reach nested form with a ref from a grandparent. This could be the case for lifting the state up.

E.g. in parent component:

  state = {
    formState: {}
  };

  onFormChange = (formState) => {
    this.setState(state => ({
      formState: { ...state.formState, ...formState }
    }));
  }

  render() {
    return (
      <Form state={this.state.formState} onChange={this.onFormChange} />
    );
  }

In form component:

  handleChange = e =>
    this.props.onChange({
      [e.target.name]: e.target.value
    });

  render() {
    return (
        <input
          onChange={this.handleChange}
          name="firstName"
          value={this.props.state.firstName}
        />
    );
  }

Here is a demo.

Upvotes: 0

masongzhi
masongzhi

Reputation: 164

you can write the code like this

https://codesandbox.io/s/23o469kyx0

Upvotes: 0

Kenzk447
Kenzk447

Reputation: 525

To access a child instance from parent, your need to know about ref:

First, add formRef at top your App class:

formRef = React.createRef();

Then in App render, pass ref prop to your Form tag:

<Form ref={this.formRef} />

Finaly, get state from child form:

save = () => {
    alert("how to get state of Form?");

    const form = this.formRef.current;
    console.log(form.state)
};

Checkout demo here

Upvotes: 7

hannad rehman
hannad rehman

Reputation: 4341

ideally, your form submit action belongs to the Form component You can put button inside your From component and pass a submit callback to the form.

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

   save = (data) => {
     // data is passed by Form component
    alert("how to get state of Form?");
    //fire api call
  };
  render() {
    return (
      <div>
        <Form onFormSubmit={this.save} />
      </div>
    );
  }
}

Upvotes: 0

Related Questions