FRONT-END/REACTJS

Render Props pattern

JINGMONG 2023. 2. 22. 15:34

💡 Render props pattern 이란?

render props는 코드의 재사용성을 높임과 동시에, 관심사의 분리를 이룰 수 있도록 만들어주는 패턴 render props란 props에 넘겨주는 값이 JSX요소를 반환하는 함수는 prop을 말한다.

 

<Title render={() => <h1>hello world</h1>} />

render 라는 prop에 JSX Element를 반환하는 함수를 넣어 사용한다.

const Title = ({ render }) => render();

예시

drawing dream 프로젝트에서 회원가입 시 입력 값에 대해 유효성 검사를 진행하였다.

render props pattern을 적용하기 전 프로젝트의 구조

SignUp.js
└ InputContainer.jsInput.js
   └ ValidContainer.js

SignUp.js 에 회원가입에 필요한 정보 뿐만 아니라 검사 결과에 해당하는 값을 저장하는 state까지 SignUp.js의 책임 이상의 데이터를 할당하고 있다. 또한 Input.js와 VslidContainer.js 두가지 컴포넌트를 묶어 두기위한 InputContainer.js라는 컴포넌트를 추가하여 사용하였다.

 

책임의 관점에서 각 컴포넌트를 바라보면

 

SignUp.js: 회원 가입을 하라

Input.js: 정보를 입력 받아라

ValidContainer: 유효성 검사를 하라

 

라고 결정하였고 이 관점에서 새로운 구조를 설계해보면

SignUp.jsInput.js
└ ValidationText.js

로 변경할 수 있었다.

새로 작성한 코드

Input.tsx

import React, { useState } from 'react';

type InputType = {
  render?: (value: string) => JSX.Element;
}

const Input = ( { render }  : InputType) => {
  const [value, setValue] = useState<string>(""); 

  const handelChange = (inputValue: string) => {
    setValue(inputValue)
  }

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

export default Input;

ValidationText.tsx

import React, { useEffect, useState } from 'react';

enum errorValue {
  init = "",
  error = "8 ~ 12자리 영문 대소문자와 숫자로 입력해주세요."
}

type validationTextType = {
  value: string
}

const ValidationText = ({ value }: validationTextType) => {
  const [error, setError] = useState<errorValue>(errorValue.init);
  
  useEffect(() => {
    const regExp = /^[a-zA-Z0-9]{8,12}$/;
    if (!regExp.test(value)) {
      setError(errorValue.error);
    } else {
      setError(errorValue.init);
    }
  }, [value])

  return (
    <div>
      { error }
    </div>
  );
};

export default ValidationText;

App.tsx

import { useEffect, useState } from "react";
import Input from "./components/Input/Input";
import ValidationText from "./components/Input/ValidationText";

function App() {

  return (
    <>
      <Input
        render={(value: string) => (
          <>
            <ValidationText value={value} />
          </>
        )}
      />
      <Input />
    </>
  );
}

export default App;

결과

Input.js 와 ValidationText.js를 묶어 두기 위한 새로운 컴포넌트를 설계하지 않아도 되는 장점이 있음.

Input.js 재사용성 증가와 유연한 설계가 가능함.

책임의 관점으로 조금더 명확한 캡슐화가 가능함.

단, 결국 유효성 검사를 한 결과를 SignUp.js에게 전달 하여하는 것을 동일함. ContextAPI 또는 전역 상태 관리 라이브러리 등을 사용하여 좀더 유연한 대처가 가능할 수 있도록 설계하는 것이 좋을 것 같음.

'FRONT-END > REACTJS' 카테고리의 다른 글

StoryBook  (0) 2022.03.05
리덕스 라이브러리  (0) 2022.02.19
Context API  (0) 2022.02.19
react 비동기 작업  (0) 2022.02.19
react route로 SPA 개발  (0) 2022.02.19