Render Props와 상태 끌어올리기에 관한 고찰

Jaewoo Gwak·2022년 9월 29일
1

React

목록 보기
1/2
post-thumbnail

Render Props

Render Props란 리액트 컴포넌트간에 코드를 공유하기 위해 함수 props를 이용하는 간단한 테크닉이다.

Render props 패턴으로 구현된 컴포넌트는 자체적으로 렌더링 로직을 구현하는 대신에 리액트 엘리먼트 요소를 반환하고 이를 호출하는 함수를 사용한다.

기존에는 컴포넌트의 return 안에서 렌더링할 컴포넌트를 구현했었다. 대신 Render props 패턴에서는 렌더링할 컴포넌트를 반환하는 함수를 사용한다.

그래서 Render props는 무엇을 렌더링할지 컴포넌트에 알려주는 함수이다. 즉, Render props는 JSX를 리턴하는 함수라고 할 수 있다.

Render props의 개념은 컴포넌트에게 동적으로 렌더링할 수 있도록 해주는 함수 prop을 제공하는 것이다.

방법1. 상태 끌어올리기

리액트에서 상태를 공유하는 일반적인 방법은 상태 끌어올리기이다.

상위 컴포넌트인 App에서 Input이 의존하는 값인 value와 업데이트 함수 setValue를 선언하였다.

그리고 Input 컴포넌트에 핸들링 함수를 넘겨주는 방식이다.

이렇게하면 부모 컴포넌트인 App의 상태를 자식인 Input에서 업데이트한다. 그리고 또 다른 자식인 KelvinFahrenheit에게 업데이트된 value를 넘겨줄 수 있다.

import { useState } from "react";
import Fahreheit from "./components/Fahreheit";
import Kelvin from "./components/Kelvin";

function Input({value, handleChange}) {
  return (<input value={value} onChange={(e) => handleChange(e.target.value)} />);
};

export default function App() {
  const [value, setValue] = useState("");

  return (
    <div className="App">
      <h1>Temperature Converter</h1>
      <Input value={value} handleChange={setValue}/>
      <Kelvin value={value} />
      <Fahreheit value={value} />
    </div>
  );
}

방법2. Render Props Pattern

위 로직을 Render Props 패턴으로 구현해보자.

기존 App에 위치하던 상태를 Input으로 내렸다. 또한 Input의 props인 render에 하위 컴포넌트 두 개 <Fahreheit /><Kelvin />을 리턴하는 함수를 전달한다.

import { useState } from "react";
import Fahreheit from "./components/Fahreheit";
import Kelvin from "./components/Kelvin";

function Input(props) {
  const [value, setValue] = useState("");

  return (
    <>
      <input value={value} onChange={(e) => setValue(e.target.value)} />
      {props.render(value)}
    </>
  )
};

export default function App() {
  return (
    <div className="App">
      <h1>Temperature Converter</h1>

      <Input render={(value) =>
        <>
          <Fahreheit value={value} />
          <Kelvin value={value}/>
        </>
      }/>
    </div>
  );
}

Render props 패턴은 어떤 컴포넌트를 렌더링할지에 대한 렌더링 로직을 상위 컴포넌트가 가지고 있고, 하위 컴포넌트인 Input은 자신이 가지고 있는 상태 값으로 내려받은 렌더링 로직과 조합하여 사용하는 것이다.

이때 하위 컴포넌트는 자신이 가진 상태를 내려받은 render props 함수를 통해 다른 컴포넌트들과 상태를 공유할 수 있다.

생각 정리

그렇다면 일반적으로 부모 컴포넌트로 상태를 끌어올리는 방법과 Render Props Pattern 사이에는 어떤 차이가 존재할까?

기존 방법은 하위 컴포넌트인 Input의 상태를 공유하기 위해 상위 컴포넌트로 끌어 올려야만 했다.
그렇게 하면 다른 하위 컴포넌트에게 상태를 공유할 수 있게 된다.

이에 반해 Render Props Pattern은 Input의 상태를 굳이 끌어올릴 필요가 없다.

Input의 상태는 Input 컴포넌트가 가지고 있다.

이 점은 아주 좋다. 굳이 상태 공유를 위해 상위 컴포넌트로 상태를 끌어올릴 필요가 없으니.

그러나 Render props로 넘겨 받은 함수의 인자로 상태 값을 넘겨서 다른 컴포넌트와 상태를 공유하는 아래의 코드는 뭔가 직관적으로 다가오진 않는다. (아직까지는..)

function Input(props) {
  const [value, setValue] = useState("");

  return (
    <>
      <input value={value} onChange={(e) => setValue(e.target.value)} />
      {props.render(value)} // render 함수의 인자로 상태를 넣으면 다른 컴포넌트들과 상태 공유가 가능하다.
    </>
  )
};

익숙치 않던 패턴이라 그런건지 아직은 적응이 필요해보인다.

실제 프로젝트에도 조금씩 적용해보고 이에 대한 코드 리뷰도 필요해보인다.

결국은 재사용성을 위함이고 추후에 Hook Pattern을 더 공부하면서 효율성 및 재사용성에 관해 고민을 해보아야겠다.

profile
꾸준하게 나아가고 싶다

0개의 댓글