DEV Community

Paramanantham Harrison
Paramanantham Harrison

Posted on • Originally published at learnwithparam.com on

How to sync props to state properly in React Hooks

First of all, you need to atleast know the basic of useState and useEffect. So that you can understand the example better.

We are going to see two cases

  1. How to pass props to state in React Hooks
  2. How to sync props to state in React Hooks

Passing props to state using useState Hooks

import React, { useState } from 'react';

const Profile = props => {
  const [profileState, setProfileState] = useState(props);
  return (
    <div>
      <p>
        <strong>Name:</strong>
        {profileState.name}
      </p>
      <p>
        <strong>Email:</strong>
        {profileState.email}
      </p>
    </div>
  );
};

export default Profile;
Enter fullscreen mode Exit fullscreen mode

Its a simple component which accepts props. We pass this props as initialState to useState.

Now, what will happen if the props get changed and does the state get changed and re-render?

No, it won’t. The state will remain the same, useState won’t initialize on props change. Let see it in example.

const App = () => {
  const [state, setState] = useState({
    name: 'Param',
    email: 'param@gmail.com',
  });

  const handleChange = () => {
    setState({
      name: 'Vennila',
      email: 'vennila@gmail.com',
    });
  };

  return (
    <div className="App">
      <Profile {...state} />
      <button onClick={handleChange}>Change Profile</button>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Click on the button, it won’t change the profile. You can console the props updated but not the UI.

const Profile = props => {
  const [profileState, setProfileState] = useState(props);
  console.log(profileState, props);

  return (
    <div>
      <p>
        <strong>Name: </strong>
        {profileState.name}
      </p>
      <p>
        <strong>Email: </strong>
        {profileState.email}
      </p>
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

The console will show this after the button gets clicked

// profileState - { name: "Param", email: "param@gmail.com" }
// props - { name: "Vennila", email: "vennila@gmail.com" }
Enter fullscreen mode Exit fullscreen mode

Even though the props get updated, the useState didn’t reset the state.

How to sync props to state in React Hooks

This is perfect use case for useEffect. Whenever props change, we will set the state inside useEffect.

Lets change the example and see,

...

  useEffect(() => {
    setProfileState(props);
  }, [props]);

...
Enter fullscreen mode Exit fullscreen mode

In this way, whenever props get changed, it will set as the state inside useEffect. useEffect is primarily to handle side effects and this is one of those example for using it.

Check out the example here

Thats all folks, we will see more examples and use cases for react hooks soon πŸ˜‹

Top comments (5)

Collapse
 
guico33 profile image
guico33

Beware though, as syncing props and state is usually an anti-pattern.

Collapse
 
learnwithparam profile image
Paramanantham Harrison • Edited

True, we need to avoid syncing as much as possible. This is just to show an example

Collapse
 
dance2die profile image
Sung M. Kim • Edited

Thank you for the post, Paramanatham.

I am not sure if the code snippet is stripped-down version of actual code, you struggled with.

For this particular case, there'd be no need to save the prop to the state at all.

Forked Sandbox.

Edit props-to-state-react-hooks

// You can destructure only πŸ‘‡ needed props  
const Profile = ({ name, email }) => {
  return (
    <div>
      <p>
        <strong>Name: </strong>
        {name}
      </p>
      <p>
        <strong>Email: </strong>
        {email}
      </p>
    </div>
  );
};

const App = () => {
  // irrelevant code removed for brevity
  const [state, setState] = useState({ ... });
  const handleChange = () => { ...  };

  return (
    <div className="App">
      {/* Pass only "needed" props πŸ‘‡ /*}
      <Profile name={state.name} email={state.email} />
      <button onClick={handleChange}>Change Profile</button>
    </div>
  );
};

Now the Profile is dumb component, which depends on the props only, which also you can further optimize using useMemo or memo()

Collapse
 
learnwithparam profile image
Paramanantham Harrison

Thanks Kim, I understood, this example doesn't make much sense. It was created just to showcase how to sync props to state if there is a need for internal state change without the props change.

Example in a tabbed layout where you already have the data as props, but the current tab has internal data changes which are not used outside. In this case, there is no need to lift the state to parent but can be managed inside the tab and have props as the initial state.

Collapse
 
kaiyizhouatbl profile image
ZhaoYiKai

useToastify
I saw a good way