How do I call setState from another Component in ReactJs
Asked Answered
C

3

29

I have two react components and I'd like to call setState to set a state in the one Component but called in the other one. How do I do that?

Codeclination answered 6/3, 2019 at 17:7 Comment(2)
Have a function that sets the state on the parent component and pass that function to the child component.Peterman
Possible duplicate: #52983602Antonantone
B
62

If you work with functional components you can use hooks like useState. Don't forget to "save" (memoize) the reference of your handler with useCallback, it helps React avoid useless rerenders.

Functional component solution

// myContainer.js
import React, { useState } from 'react'
import MyChild from 'some/path/myChild'

function MyContainer() {
  const [name, setName] = useState('foo')

  return (
    <MyChild name={name} onNameChange={setName} />
  )
}

export default MyContainer

// myChild.js
import React, { useCallback } from 'react'

function MyChild({ name, onNameChange }) {

  const handleInputChange = useCallback(event => {
    onNameChange(event.target.value)
  }, [onNameChange])

  return (
    <div>
      <input type="text" onChange={handleInputChange} value={name} />
      <div>The name is: {name}</div>
    </div>
  )
}

export default MyChild

In a class you can use handler (method) that contains some logic or function call(s). It help to keep your code maintainable.

Class component solution

// myContainer.js
import React, { Component } from 'react'
import MyChild from 'some/path/myChild'

class MyContainer extends Component {
  state = {
    name: 'foo'
  }

  handleNameChange = name => {
    this.setState({ name })
  }

  render() {
    return (
      <MyChild name={this.state.name} onNameChange={this.handleNameChange} />
    )
  }

}

export default MyContainer

// myChild.js
import React, { Component } from 'react'

class MyChild extends Component {

  handleInputChange = event => {
    this.props.onNameChange(event.target.value)
  }

  render() {
    return (
      <div>
        <input type="text" onChange={this.handleInputChange} value={this.props.name} />
        <div>The name is: {this.props.name}</div>
      </div>
    )
  }

}

export default MyChild
Bornite answered 6/3, 2019 at 17:16 Comment(2)
Hi, my situation is the inverse. Trying to change state in child functional component from a button click on the parent functional component. Also, there are multiple child components with a button each in a loop. How would I make sure only one of them updates? Thanks in advance!Goshen
@SanjivPradhanang Perhaps you could open a question thread, expose your issue with code example. That would be easier to propose solutions.Bornite
W
17

You can't directly call setState on a parent component from a child component because the updating of a component state is restricted to the current component.

To handle this, simply pass a function from the parent to the child that contains setState. So when you want to update the parent's state, just call that passed function.

A minimal example:

// Parent.jsx

import React, { Component } from 'react';
import Child from './Child';

class Parent extends Component {
  constructor(props) {
    super(props);
    this.setChanged = this.setChanged.bind(this);
    this.state = {
      changed: false
    }
  }

  // Function to set the parent's state
  setChanged() {
    this.setState({ changed: true });
  }

  render() {
    return <Child setChanged={this.setChanged} />
  }
}

// Child.js

import React from 'react';

function Child(props) {
  return (
    // When clicked, parent's setChanged function is called
    <div onClick={() => props.setChanged()} />
  )
}
Wheeling answered 6/3, 2019 at 17:27 Comment(2)
thanks for your response although I went with KornflexxsCodeclination
TypeError: props.setChanged is not a functionMoise
K
0

clickfun in the following example for sent it from other component where it represent function that call setstate in parent

import React, { useState } from 'react';
import './Testcomponent.css';



const Testcomponent = ({clickfun}) => {



return (
<div>
  
  {(
    <div className="popup">
      <div className="popup-inner">
        <h2>Popup Content</h2>
        <p>This is a popup or modal.</p>
        <button onClick={clickfun} >Close</button>
      </div>
    </div>
    )}
  </div>
 );
 };

export default Testcomponent;

parent example :

const [isOpen, setIsOpen] = useState(false);

const togglePopup = () => {
  setIsOpen(!isOpen);
};

<Button onClick={togglePopup}> call child button (popup example) 
</Button>
{isOpen && <Testcomponent clickfun={togglePopup} ></Testcomponent>}
Know answered 4/7 at 17:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.