React Context API를 사용하여 중첩 구성 요소에 값 전달

내가 2018년에 React를 배우기 시작했을 때 후크는 아직 존재하지 않았습니다. 렌더링할 구성 요소를 가져오는 데 어려움을 겪고 있고 부모에서 자식으로 소품을 전달해야 하므로 또 다른 수준의 복잡성이 추가되었기 때문에 이것은 매우 힘든 작업이었습니다.

2022년으로 돌아가 React를 다시 플레이하기 시작하고 인터뷰 중에 React Context API에 대해 알게 됩니다.

“Context provides a way to share values like these between components without having to explicitly pass a prop through every level of the tree.”




너무 간단하게 들리지만 마음을 감싸고 의미있는 방식으로 사용하는 데 시간이 걸렸습니다.

배경



우리 회사에는 TextButton와 같은 재사용 가능한 React UI 구성 요소 라이브러리가 있어 이러한 구성 요소를 개별적으로 테스트하고 나중에 제품 UI에 연결하기가 쉽습니다.


저는 webauthn을 사용하여 암호가 필요 없는 새로운 로그인 흐름을 만드는 일을 돕고 있습니다. 디자인에는 여러 카드가 있으며 각 카드에는 사용자의 진행 상황을 자세히 설명하는 헤더, 제목 및 링크가 있습니다. 이것은 일반적인 디자인 모델이므로 다른 프로젝트에서 재사용할 수 있도록 UI 라이브러리에 재사용 가능한 구성 요소를 만들기로 결정했습니다.

도전



컴포넌트 라이브러리가 있으므로 기존 컴포넌트를 결합하고 수정하여 이 새로운 컴포넌트를 만들겠습니다.



기존 Surface (배경색) 및 Text 구성 요소를 사용합니다. 선택한 배경색을 기준으로 보색 텍스트 색상을 페어링하고 싶습니다. 배경색이 텍스트 색상을 결정하므로 Surface 로 시작하여 배경색을 Text 에 전달하고 마지막으로 Heading 에 전달합니다. 이를 위해 React의 Context API를 사용하여 각 수준에서 수동으로 소품을 전달하지 않고 구성 요소 트리를 통해 데이터를 전달합니다.

내가 한 방법



먼저 내 Surface 구성 요소에 대한 테마를 만듭니다. 구성 요소 라이브러리에는 이미 기존 테마가 있으므로 이 구성 요소별 테마에 대해 해당 색상을 가져옵니다. 여기에서는 다양한 배경색을 통해 매핑하고 보색 텍스트 색상과 쌍을 이룹니다.

// Here I bring in the existing theme values to the surface theme
import { TextVariant, SurfaceVariant } from '../../types';

// Since this is TypeScript, I define the shape of my theme
export interface SurfaceTheme{
 variant: { [key in SurfaceVariant]: TextVariant };
}

// This is the theme with the color pairings
export const surfaceDefaultTheme:SurfaceTheme= {
 variant: {
  [SurfaceVariant.PRIMARY]: TextVariant.NORMAL,
  [SurfaceVariant.SECONDARY]: TextVariant.DARK,
  [SurfaceVariant.TERTIARY]: TextVariant.ACCENT,
 },
};


다음으로 WordPress에서 React Context API의 함수인 createContext 를 가져옵니다. 위와 마찬가지로 컨텍스트 개체의 모양에 대한 인터페이스를 만들고 컨텍스트 값을 보유할 변수를 할당합니다.

import { createContext } from '@wordpress/element';

// The shape of the context object
interfaceSurfaceContext{
 textVariant: TextVariant;
}

// Using createContext, I passed the acceptable value types and gave it a 
// default value of undefined
export const SurfaceContext =createContext<SurfaceContext| undefined>(
 undefined
);


내 Surface 함수 내에서 (테마를 통해) 표면 테마 데이터를 가져오고 소품에 변수variant를 할당하고 변수가 없는 경우 사용할 기본값을 지정합니다. 그런 다음 텍스트 색상을 유지하기 위해 contextValue를 할당하고 컨텍스트 제공자에게 소품으로 전달합니다. 이것은 내 구성 요소 트리의 최상위 수준입니다.

export function Surface(props:SurfaceProps) {
// Get surface theme
 const {
  components: { surface },
 } =useTheme();

// Get the surface variant | assign to Primary
 const { variant = SurfaceVariant.PRIMARY } = props;

// Create an object with the text color
 const contextValue = { textVariant: surface.variant[variant] };

 return (
// Pass the text color to the React Context Provider
  <SurfaceContext.Provider value={contextValue}>
   <StyledSurface {...props} />
  </SurfaceContext.Provider>
 );
}


첫 번째 하위 구성 요소인 Text 로 이동하여 useContext React Context 함수와 SurfaceContext에서 내 Surface 변수를 가져옵니다. Text 함수 내에서 이러한 값을 보유할 변수를 할당합니다. 그런 다음 텍스트 구성 요소에 대한 소품으로 변형 매개변수에 일련의 값을 할당합니다.

import { useContext } from '@wordpress/element';

import { SurfaceContext } from '../surface';

export function Text({
// params
// ...
variant
}: TextProps) {
    const surfaceContext = useContext(SurfaceContext);
...
return (
<Component
       // If the user explicitly passes a text color, 
       // that should be honored.
       // Otherwise use the text color from the surface 
       // theme if defined
       // Or, default to normal text color
    variant= {
         variant || surfaceContext?.textVariant || TextVariant.NORMAL
} />


마지막으로, 우리는 이러한 노력의 전체 이유인 Header 구성 요소에 도달합니다. 이 구성 요소는 SurfaceText 구성 요소로 구성되어 있으므로 여기에서 수행할 작업이 없습니다. 모든 배경색/텍스트 색상 정보는 해당 구성 요소에서 수신되며 이 구성 요소에서 올바르게 렌더링됩니다.

약간 반투명하지만 이것이 React Context API의 마법입니다. 바로 작동합니다.

작동 중인 완성된 구성 요소는 다음과 같습니다.



저는 직접 해보면서 가장 잘 배우기 때문에 프로세스를 완전히 이해하려면 실제 프로젝트가 필요했습니다. 나는 주로 나 자신을 위해 개념을 확고히 하기 위해 여기에 설명하지만 아마도 Context API를 사용하는 동안 어려움을 겪는 일부 부분을 연결하는 데 도움이 될 것입니다.

주제에 대한 추가 정보가 필요하면 다음 리소스를 확인하세요.
  • React Context
  • Hooks API Reference
  • WordPress Element Package
  • 좋은 웹페이지 즐겨찾기