Search code examples
reactjscomponentssetstate

How do I call setState from another Component in ReactJs


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?


Solution

  • 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