React를 사용한 메타프로그래밍

Mar 09 2023
목적은 메타프로그래밍이 무엇인지와 그 기법에 대해 자세히 설명하는 것이 아니라 React에서 메타프로그래밍을 적용하는 방법의 예를 보는 것입니다. 이것은 이 환상적인 매체에 대한 나의 첫 번째 게시물이며, 우리가 이미 한 번 (프로그래머로부터) 사용했지만 자세히 알지 못할 수도 있는 한 가지 기술인 메타프로그래밍에 대해 조금 쓰고 싶습니다! 아래 코드는 React 구성 요소 내에서 Proxy 구성 및 Reflect API를 사용하는 방법의 예입니다.
Unsplash에 있는 Lautaro Andreani의 사진

목적은 메타프로그래밍이 무엇인지와 그 기법에 대해 자세히 설명하는 것이 아니라 React에서 메타프로그래밍을 적용하는 방법의 예를 보는 것입니다.

이것은 이 환상적인 매체에 대한 나의 첫 번째 게시물이며, 우리가 이미 한 번(프로그래머로부터) 사용했지만 자세히 알지 못할 수도 있는 한 가지 기술인 메타프로그래밍 에 대해 조금 쓰고 싶습니다 !

아래 코드는 React 구성 요소 내에서 Proxy 구성 및 Reflect API를 사용하는 방법의 예입니다 . MyComponent 구성 요소는 React의 로컬 상태( useState ) 를 사용하여 초기에 비어 있는 " test " 속성이 있는 proxyData 개체를 관리합니다 . 구성 요소에는 클릭 시 proxyData 개체의 "test" 속성을 수정하는 세 개의 버튼이 있습니다.

import React, { useState } from 'react';

function MyComponent() {
  const [proxyData, setProxyData] = useState({ test: '' });
  const [render, setRender] = useState(false);

  const handleClickMemo = React.useCallback(() => {
    const updatedData = new Proxy(proxyData, {
      set(target, prop, value) {
        const success = Reflect.set(target, prop, value);
        if (success) {
          console.log(`Prop ${prop} modified with value ${value}`);
        }
        return success;
      },
    });
    updatedData.test = crypto.randomUUID();
    setProxyData(updatedData);
  }, []);

  // without useCallback, do new proxy every time
  const handleClick = () => {
    const updatedData = new Proxy(proxyData, {
      set(target, prop, value) {
        const success = Reflect.set(target, prop, value);
        if (success) {
          console.warn(`Prop ${prop} modified with value ${value}`);
        }
        return success;
      },
    });
    updatedData.test = crypto.randomUUID();
    setProxyData(updatedData);
  };

  // case where react doesn't render, but in console,
  // if it is a proxy the object is updated
  // BE CAREFUL when using proxies
  const handleClickNoRender = () => {
    proxyData.test = crypto.randomUUID();
    setProxyData(proxyData);
  };

  return (
    <div>
      <pre>{JSON.stringify(proxyData)}</pre>
      <button onClick={handleClickMemo}>handleClickMemo</button>
      <button onClick={handleClick}>handleClick</button>
      <button onClick={handleClickNoRender}>handleClickNoRender</button>
      <br />
      <button onClick={() => setRender(!render)}>re-render</button>
    </div>
  );
}

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

첫 번째 버튼인 handleClickMemo 는 React.useCallback 함수를 사용하여 React에 의해 캐시되는 함수를 생성합니다. 이는 구성 요소가 업데이트될 때마다 함수가 다시 빌드되는 것을 방지하는 데 유용합니다. 이 함수는 proxyData 개체를 기반으로 새 프록시 개체를 만들고, 임의로 생성된 새 값으로 "test" 속성을 업데이트하고, 새로 만든 개체로 proxyData 의 상태를 설정합니다 .

const handleClickMemo = React.useCallback(() => {
    const updatedData = new Proxy(proxyData, {
      set(target, prop, value) {
        const success = Reflect.set(target, prop, value);
        if (success) {
          console.log(`Prop ${prop} modified with value ${value}`);
        }
        return success;
      },
    });
    updatedData.test = crypto.randomUUID();
    setProxyData(updatedData);
  }, []);

// without useCallback, do new proxy every time
  const handleClick = () => {
    const updatedData = new Proxy(proxyData, {
      set(target, prop, value) {
        const success = Reflect.set(target, prop, value);
        if (success) {
          console.warn(`Prop ${prop} modified with value ${value}`);
        }
        return success;
      },
    });
    updatedData.test = crypto.randomUUID();
    setProxyData(updatedData);
  };

// case where react doesn't render, but in console,
  // if it is a proxy the object is updated
  // BE CAREFUL when using proxies
  const handleClickNoRender = () => {
    proxyData.test = crypto.randomUUID();
    setProxyData(proxyData);
  };

프록시를 사용하면 부작용이 있을 수 있으며 올바르게 사용하지 않으면 성능 문제가 발생할 수 있다는 점에 유의해야 합니다 . 또한 프록시 객체를 통한 상태 업데이트는 React에서 감지하지 못할 수 있으므로 React 구성 요소 내에서 프록시를 사용할 때 주의해야 합니다.

이 링크 에서 콘솔에서 각 버튼의 동작을 볼 수 있습니다.