简体   繁体   中英

React JS : Calling Child component method within parent component (React with typescript)

I am trying to create a custom number picker component and trying to add it to the components wherever it is needed. But When I am trying to fetch the number picker value in the Parent component , I am getting the older value . Can someone help me with this?

Number Picker Component

import * as React from "react";

interface IState {
  value: number;
}

interface IProps {
  setValue(val: number): void;
}

class NumberPicker extends React.Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      value: 0
    };
  }

  public doDecrement = () =>
    // DECREMENT CODE
    {
      if (this.state.value < 1) {
        console.log("LESS THAN O");
      } else {
        this.setState({
          value: this.state.value - 1
        });
        this.props.setValue(this.state.value);
      }
    };

  public doIncrement = () =>
    // INCREMENT CODE
    {
      this.setState({
        value: this.state.value + 1
      });
      this.props.setValue(this.state.value);
    };

  public handleChange = (
    e: React.ChangeEvent<HTMLInputElement> // CHANGE HANDLER
  ) => {
    const val = parseInt(e.target.value);
    this.setState({ value: val });
  };

  public render() {
    return (
      <div>
        <button
          onClick={this.doDecrement}
          className="fa fa-minus fa-inverse fa-2x"
        />
        <input
          type="text"
          className="number"
          value={this.state.value}
          onChange={this.handleChange}
        />
        <button
          onClick={this.doIncrement}
          className="fa fa-plus fa-inverse fa-2x"
        />
      </div>
    );
  }
}
export default NumberPicker;

PARENT COMPONENT CODE

import * as React from "react";
import NumberPicker from "./NumberPicker";

interface IState {
  val: number;
}

interface IProps {}

class Parent extends React.Component<IProps, IState> {
  constructor(props: any) {
    super(props);
    this.state = {
      val: 0
    };
  }

  handleVal = (value: number) => {
    this.setState({ val: value }, () => console.log(this.state.val));
  };

  render() {
    return (
      //Some fields along with the below numberpicker
      <NumberPicker setValue={this.handleVal} />
    );
  }
}

export default Parent;

I have tried using setState's callback function as well, but it does not seem to be working . Parent component always shows the older value.How will I get the updated value of the NumberPicker inside parent? Help would be appreciated!

React's setState is asynchronous, and because of that this.props.setValue function is going to be called before setState has updated your state in child Numberpicker component. This is why an old value is passed to the parent component.

Instead you can call this.props.setValue inside setState 's callback function.

 public doIncrement = () =>
    // INCREMENT CODE
    {
      this.setState({
        value: this.state.value + 1
      }, () => {
              this.props.setValue(this.state.value);
         });

    };
public doDecrement = () =>
    // DECREMENT CODE
    {
      if (this.state.value < 1) {
        console.log("LESS THAN O");
      } else {
        this.setState({
          value: this.state.value - 1
        }, () => {
              this.props.setValue(this.state.value);
           });
      }
    };

setState is not a synchrounous function. So when you are calling the callback from parent you are calling it with old state value, because new value will be set sometime in future. You can call the callback with the same value you are setting to state: this.state.value - 1 or this.state.value + 1. It should work as expected. I also recommend to read thinking in react for better intuition about where you should hold your state.

Don't use state for passing values in callback, you can do like:-

  handleChange = (
    e: React.ChangeEvent<HTMLInputElement> // CHANGE HANDLER
  ) => {
    const val = parseInt(e.target.value);
    // this.setState({ value: val });
    this.props.setValue(val);
  };

i hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM