score:52

Accepted answer

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

score:16

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()} />
  )
}

Related Query

More Query from same tag