[Resolved] useState not showing updated value – Deploy Callback and useEffect to Solve

When trying to get the updated state from the child to parent component, it is not updating the latest value in the console or JSX template.

Sometimes when updating the state in a functional or class component in React, does not reflect the updated values immediately. This happens due to the asynchronous behaviour of state variables which takes time to update in the internal state.

So if you try to console or render that value, it will show the previous value instead of the latest one. Let’s have a look on problem code below:

Problem: useState not reflecting Value for first time

In our example app, the parent App functional component is going to get the value from child component on button click.

The App.js file which is acting as a parent component:

import React, { useState, useEffect } from 'react';
import ChildComponent from './child.component';
import './style.css';

export default function App() {
  const [appvalue, setAppvalue] = useState('');

  function fromChildValue(value) {
    setAppvalue(value);
    console.log('App comp value:', appvalue);
  }

  return (
    <div>
      <h1>Parent Component Getting Value from Child</h1>

      <ChildComponent childValue={fromChildValue} />
    </div>
  );
}

 

Now, we have the ChildComponent in the ~src/child.component.js file with following code:

import React from 'react';

class ChildComponent extends React.Component {
  constructor() {
    super();
    this.state = {
      value: ''
    };
  }

  onSubmit() {
    this.setState({
      value: 'text from child'
    });
    this.props.childValue(this.state);
  }

  render() {
    return (
      <div>
        <button onClick={() => this.onSubmit()}>Send Value</button>
      </div>
    );
  }
}

export default ChildComponent;

 

When you click on the button it will show an empty value, even though we have set the state variable value.

 

Solution:

To solve this issue, we need to modify the Parent as well as Child components as suggested below:

In the Child component, instead of sending back the value in a different states, we need to use the callback of the setState function as shown below:

import React from 'react';

class ChildComponent extends React.Component {
  constructor() {
    super();
    this.state = {
      value: ''
    };
  }

  onSubmit() {
    this.setState(
      {
        value: 'text from child'
      },
      () => this.props.childValue(this.state)
    );
  }

  render() {
    return (
      <div>
        <button onClick={() => this.onSubmit()}>Send Value</button>
      </div>
    );
  }
}

export default ChildComponent;

In the App.js, we need to call the useEffect hook, to get state value when it is updated:

import React, { useState, useEffect } from 'react';
import ChildComponent from './child.component';
import './style.css';

export default function App() {
  const [appvalue, setAppvalue] = useState('');

  function fromChildValue(value) {
    setAppvalue(value);
  }

  useEffect(() => {
    console.log('App comp value:', appvalue);
  }, [appvalue]);

  return (
    <div>
      <h1>Parent Component Getting Value from Child</h1>

      <ChildComponent childValue={fromChildValue} />
    </div>
  );
}

By deploying the useState callback to send back value and usage of useEffect hook in parent functional compoennt will resolve this issue:

Leave a Reply

Your email address will not be published. Required fields are marked *