user3055126
user3055126

Reputation: 299

Advantages of rendering a component vs a function returning JSX [React]

I understand that, within your React component, it's always good to render a component rather than use a function that renders some JSX. What I mean is,

Doing this :

export default function App() {
  const [count, setCount] = useState(0);
  const someRenderFunction = () => <p>Hey</p>;
  return (
    <div className="App">
      {someRenderFunction()}
      <button
        onClick={() => {
          setCount((c) => c + 1);
        }}
      >
        Increment{" "}
      </button>
      <p>{count}</p>
    </div>
  );
}

is NOT encouraged. The render function should be exported into it's own Component, like this :

const HeyComponent = () => <p>Hey</p>

export default function App() {
  const [count, setCount] = useState(0);
  return (
    <div className="App">
      <HeyComponent />
      <button
        onClick={() => {
          setCount((c) => c + 1);
        }}
      >
        Increment{" "}
      </button>
      <p>{count}</p>
    </div>
  );
}

But I never really understood the benefits of this refactor. I tried placing checking the re-render behaviours, unmount behaviours. Still didn't see any difference. Can anyone explain in detail why this refactor is necessary/beneficial ?

Upvotes: 16

Views: 6042

Answers (4)

allieferr
allieferr

Reputation: 328

Two reasons why the second way is better than the first way are:

  1. The function which defines the <p>Hey</p> JSX (named someRenderFunction in the first way, and HeyComponent in the second) is moved outside of the component App in the second way. As of now, there's no benefit, but if you later wanted to extend someRenderFunction/HeyComponent to have normal component lifecycle that can be hooked into, moving it outside of App would be essential. For example, if you wanted the function/component to keep track of its own state, the first way would cause someRenderFunction's state to get reset every time App renders. More info on this problem can be found here: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-unstable-nested-components.md, and here: https://stackoverflow.com/a/64211013/693855.
  2. HeyComponent would be seen as a valid component whereas someRenderFunction would not, because component names need to start with a capital letter (this is mentioned here https://reactjs.org/docs/components-and-props.html#rendering-a-component in the Note at the bottom of the section). If you used hooks in your function, and it was not seen as a valid component by React, it would be breaking the "Rules of Hooks" set by React (https://reactjs.org/docs/hooks-rules.html#only-call-hooks-from-react-functions). I'm not sure if this would cause any bugs, but it is frowned upon by React -- if you have the "react-hooks/rules-of-hooks" ESLint rule enabled (from https://www.npmjs.com/package/eslint-plugin-react-hooks), you would see an error like this: ESLint: React Hook "useState" is called in function "someRenderFunction" that is neither a React function component nor a custom React Hook function.(react-hooks/rules-of-hooks)

Upvotes: 4

Heartbit
Heartbit

Reputation: 1836

This is all about components, so components should be reusable and should follow the DRY principle, in your case that seems to be so simple and just as you said will prevent the someRenderFunction() to be re-rendered if there aren't any changes to that component in the virtual dom so the best practices are to use <X /> syntax always or for some cases const Y = <X /> also is more readable. testing is another reason to create more components and make them more decoupled. imagine here you need to pass props to your someRenderFunction() so you will lose the jsx feature for passing props as <X prop={PROP}/>.

Upvotes: 4

BlackGlory
BlackGlory

Reputation: 4035

The actual difference between the two is that the function returning JSX is not a component, so it does not have its own state. When you use useState in the function, the state change will cause the App to be re-rendered.

Upvotes: 3

Pavan Kalyan
Pavan Kalyan

Reputation: 407

The code which renders a component is followed as best practice. Using Components we can pass state values to child component and can be used to display data. The same component can be re-used in other places.

If you have to just display a small function it can be used too if it shows constant information.

Upvotes: 1

Related Questions