Strive for a minimum required state in a React component
Andrey Smolko

Andrey Smolko @smlka

About: Software Engineer at Wärtsilä

Location:
Belgrade
Joined:
May 3, 2020

Strive for a minimum required state in a React component

Publish Date: Aug 27 '22
10 4

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

Comments 4 total

  • Erik Slagter
    Erik SlagterAug 27, 2022

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

    • Andrey Smolko
      Andrey SmolkoAug 27, 2022

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

      • Erik Slagter
        Erik SlagterAug 27, 2022

        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.

        • Andrey Smolko
          Andrey SmolkoAug 27, 2022

          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=)

Add comment