jhrwekuh
jhrwekuh

Reputation: 326

Changing the state of parent component inside a child

I have started learning react and I couldn't find the answer for one of my questions.

Let's say I have a parent component called main where I have states and one of them is a counter.

Inside main i have a child component called secondary with a few buttons.

Is that possible to change state of the parent component using the function inside the child component?

If not, would Redux help to solve that task?

Thanks in advance for clarification

Upvotes: 1

Views: 831

Answers (4)

Ken Labso
Ken Labso

Reputation: 911

You can update parent state by passing a function to the child component to update the parent.

Upon calling updateCounterfunction in the example, you can decrement or increment the value of count by supplying an operator in the function's argument which can be plus or minus

class Parent extends Component {
  state = {
    count: 1
  };
  updateCounter = operator => {
    if (["plus", "minus"].includes(operator)) {
      this.state(prevState => ({
        count: prevState.count + (operator === "plus" ? 1 : operator === "minus" ? -1 : 0)
      }));
    }
  }
  render() {
    const { count } = this.state;
    return (
      <Child count={count} updateCounter={this.updateCounter} />
    );
  };
};

const Child = props => (
  <div>
    <button onClick={() => props.updateCounter("minus")}>MINUS</button>
    <button onClick={() => props.updateCounter("plus")}>PLUS</button>
    <h1>{props.count}</h1>
  </div>
);

Upvotes: 0

Alvin S. Lee
Alvin S. Lee

Reputation: 5182

Your parent component can keep a state, initialized in the constructor like follows:

class Main extends Component {
  constructor (props) {
    super(props)
    this.state = { counter: 0 }
  }
  ...

Then, you want to create a method in Main that increments your state counter:

  incrementCounter = () => {
    this.setState({ counter: this.state.counter + 1 })
  }

You can pass this function reference to a child component as a prop. So, you might see this in the render method of Main:

<Child incrementParent={this.incrementCounter} />

Then, in the Child, whenever you'd like, you can call this.props.incrementParent() - and this will call the function that was passed to it from Main, which will increment the state counter for Main.

Here is a code sandbox that shows all of this put together. In it, there is a parent container (Main) with its own state counter. There is a Child component which has 3 buttons. Each button click increments its own counter, but also any button click will increment the parent's counter.

Hope this helps!

Upvotes: 4

Isaac
Isaac

Reputation: 12894

class Parent extends Component {
  state = { counter: 0 };

  updateCounter = () => {
    this.setState(prevState => ({
     counter: prevState.counter + 1
    }))
  };

  render() {
    return (
      <>
        <Text>{this.state.counter}</Text>
        <ChildComponent updateCounter={this.updateCounter} />
      </>
    );
  }
}
class ChildComponent extends Component {
  ...
  render() {
    return (<Button onPress={this.props.updateCounter}><Text>{'Press Me!'}</Text></Button>)
  }
}

You should pass the function of updating your counter updateCounter from parent, pass that reference to ChildComponent

Upvotes: 0

Keno
Keno

Reputation: 2098

Yes, you can create a function that updates the parent state, and pass it down via props, context or redux if your particular app needs it.

E.g. Using React hooks

function Parent() {
  const [value, setValue] = useState(1);

  const increment = () => {
    setValue(value + 1);
  }

  return (
    <Child increment={increment} />
  );
}

function Child(props) {
  const { increment } = props;

  return (
    <button onClick={increment} />
  );
}

Upvotes: 1

Related Questions