DEV Community

Andrey Smolko
Andrey Smolko

Posted on

3 2 1

Strive for a minimum required state in a React component

Keep a component state as minimal as possible and avoid unnecessary state synchronization .

🚫 Before refactoring - b is a redundant state which should be sync:

export default function App() {
  const [a, setA] = useState(1);
  const [b, setB] = useState(1);

  function updateA(x) {
    setA(x);
  };

  function updateB() {
    setB(1 + a);
  };

  useEffect(() => {
    updateB()
  },[a])


  return (
    <div>
      <button onClick={() => updateA(a+1)}>Click</button>
        <p>a: {a}</p>
        <p>b: {b}</p>
    </div>
)
};
Enter fullscreen mode Exit fullscreen mode

After refactoring - a is a minimum sufficient state and just derive b from it:

export default function App() {
  const [a, setA] = useState(1);

  function updateA(x) {
    setA(x);
  };

  function updateB() {
    return a+1
  };

  return (
    <div>
      <button onClick={() => updateA(a+1)}>Click</button>
      <p>a: {a}</p>
      <p>b: {updateB()}</p>
    </div>
  )
};
Enter fullscreen mode Exit fullscreen mode

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (4)

Collapse
 
erik_slagter profile image
Erik Slagter

Both examples are anti patterns, I would suggest looking into useMemo for derived/calculated properties

Collapse
 
smlka profile image
Andrey Smolko • Edited

May you clarify what is a problem with a second? If it is just about wrap in useMemo then I say "Measure first".

Collapse
 
erik_slagter profile image
Erik Slagter • Edited

I would say calling a function inside the template is not great for visibility and debug-ability. Define const b = useMemo(() => ..., [a]) on top, so you have a clear view of all variables inside your functional component.

Defining state variables doesn't cost anything, replacing them with an uncached function call, is not great.

In your example you are doing some very basic calculation on a + 1, but in real life you want to keep your derived variables in useMemo. Keeping strict to good habits will help you preventing performance bugs. It might not look/feel slow, but it adds a little computation to every render.

Thread Thread
 
smlka profile image
Andrey Smolko • Edited

Regarding first part I agree, it is better for readability to define a separate variable b instead of just a function call.

I would argue that wrap all derived variables in useMemo by default is a good habit. Most of real life function calls which returns derived values are extremely fast. I think you know the phrase about premature optimization and evil=)

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay