Languages
[Edit]
EN

React - change state from props (functional component)

3 points
Created by:
Dirask Community
6240

In this article, we would like to show you how to change component state from props in React when we work with functional components.

This article shows two approaches:

  • with useEffect what is the most popular approach in many projects that causes┬áadditional re-rendering component cycle,
  • with a┬ácustom hook that bases on useRef┬á- which is the optimal solution.

1. useEffect approach example

Below example uses two functional components: MyComponent and App.

States are stored in globalCounter and localCounter. Every button click action inside App component causes passing globalCounter into MyComponent localCounter state via counter props. useState creates state with indicated value only once, so in the below case useState(counter) with new couter value will not cause state change. By using useEffect hook we are able to monitor counter prop value with indicating dependencies via [counter] and update localCounter value with setLocalCounter function always when useEffect detects couter value changes.

// ONLINE-RUNNER:browser;

//Note: Uncomment import lines during working with JSX Compiler.
// import React from 'react';
// import ReactDOM from 'react-dom';

const MyComponent = ({counter}) => {
  const [localCouter, setLocalCouter] = React.useState(counter);
  React.useEffect(() => {
    setLocalCouter(counter);
  }, [counter]); // <--- when counter value is changed setLocalCouter updates local state
  return (
    <div>
      <span>localCouter={localCouter}</span>
      <button onClick={() => setLocalCouter(localCouter + 1)}>Click me!</button>
    </div>
  );
};

const App = () => {
  const [globalCounter, setGlobalCouter] = React.useState(0);
  return (
    <div>
      <span>globalCounter={globalCounter}</span>
      <button onClick={() => setGlobalCouter(globalCounter + 1)}>Click me!</button>
      <MyComponent counter={globalCounter} />
    </div>
  );
};

const root = document.querySelector('#root');
ReactDOM.render(<App />, root );

2. Optimal solution with useRef example

Below approach is a little complicated because uses references to store state. The main idea of the solution is to store state inside reference and force rerendering with counter when the state is changed.

// ONLINE-RUNNER:browser;

//Note: Uncomment import lines during working with JSX Compiler.
// import React from 'react';
// import ReactDOM from 'react-dom';

// This approach reduces unnecessary re-rendering.

const usePropState = (prop) => {
  const [counter, setCounter] = React.useState(0); // to force re-rendering only
  const currentPropRef = React.useRef(prop);       // to help in detection property change only 
  const currentStateRef = React.useRef(prop);      // stores local state
  if (currentPropRef.current != prop) {            // property change detection
    currentPropRef.current = prop;
    currentStateRef.current = prop;
  }
  return [
    currentStateRef.current,
    (newState) => {
      currentStateRef.current = newState;
      setCounter(counter => counter + 1);
    }
  ];
};

const MyComponent = ({ counter }) => {
  const [localCouter, setLocalCouter] = usePropState(counter);
  return (
    <div>
      <span>localCouter={localCouter}</span>
      <button onClick={() => setLocalCouter(localCouter + 1)}>Click me!</button>
    </div>
  );
};

const App = () => {
  const [globalCounter, setGlobalCouter] = React.useState(0);
  return (
    <div>
      <span>globalCounter={globalCounter}</span>
      <button onClick={() => setGlobalCouter(globalCounter + 1)}>Click me!</button>
      <MyComponent counter={globalCounter} />
    </div>
  );
};

const root = document.querySelector('#root');
ReactDOM.render(<App />, root );

ReactJS

React - change state from props (functional component)
Native Advertising
­čÜÇ
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

ÔŁĄ´ŞĆ­čĺ╗ ­čÖé

Join