DEV Community

Cover image for React.js ~Liftup Pattern for Preventing unnecessary rendering~
Ogasawara Kakeru
Ogasawara Kakeru

Posted on

React.js ~Liftup Pattern for Preventing unnecessary rendering~

Liftup Pattern
In contrast to the liftdown pattern,the pattern that lifts up a part of component that depends on the state can prevents unnecessary rendering.
An example below shows <SuperSlowComponent/> when hide is typed in the form.

import { useState } from "react";

function SuperSlowComponent() {
  const now = performance.now();
  while (performance.now() - now < 200) {}
  return <div>Super slow component</div>;
}

function Form({ name, setName }) {
  return (
    <>
      <label htmlFor="name">Name</label>
      <input
        id="name"
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
    </>
  );
}

export default function App() {
  const [name, setName] = useState("");
  return (
    <div className="app">
      <Form name={name} setName={setName} />
      {name !== "hide" && <SuperSlowComponent />}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

This method invokes rerendering the slow component everytime you type values in the field. For now, let's go back to managing useState in the <Form /> component instead of calling it from <App />.

By using liftup pattern, The difference from liftdown pattern is passing the slow component as a children. Since children is simply a prop, it is not affected by changes in state and therefore will not be re-rendered.

import { useState } from "react";

function SuperSlowComponent() {
  const now = performance.now();
  while (performance.now() - now < 200) {}
  return <div>Super slow component</div>;
}

function Form({ children }) {
  const [name, setName] = useState("");

  return (
    <>
      <label htmlFor="name">Name</label>
      <input
        id="name"
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      {name !== "hide" && children}
    </>
  );
}

export default function App() {
  return (
    <Form>
      <SuperSlowComponent />
    </Form>
  );
}

Enter fullscreen mode Exit fullscreen mode

As a variation of the lift-up pattern, there is also a pattern where components are passed as Props instead of being passed as children.

import { useState } from "react";

function SuperSlowComponent() {
  const now = performance.now();
  while (performance.now() - now < 200) {}
  return <div>Super slow component</div>;
}

function Form({ left, right }) {
  const [name, setName] = useState("");
  return (
    <>
      {left}
      <label htmlFor="name">Name</label>
      <input
        id="name"
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />
      {right}
    </>
  );
}

export default function App() {
  return (
    <div className="app">
      <Form right={<SuperSlowComponent />} left={<h1>Hello</h1>} />
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)