Chakra UI의 재사용 구성 요소 확장 방법

차크라 UI로 사용자 정의 구성 요소를 만들고 싶을 때 몇 가지 방법을 알게 됐다.

1. 다른 부품으로 일반 포장


가장 놀라운 방법
const RoundedOutlineButton: FC<ButtonProps> = (props) => {
  return <Button
    variant="outline"
    borderStyle="solid"
    borderWidth="2px"
    rounded="full"
    px={10}
    py={5}
    letterSpacing="0.1em"
    {...props} />
}
거의 8할은 이렇게 해결할 수 있다.
<RoundedOutlineButton>hello</RoundedOutlineButton>

// 更にもうちょっと拡張したいなら
<RoundedOutlineButton p={10}>hello</RoundedOutlineButton>
  • 이점
  • 가장 간단
  • 기타 영향 없음
  • 단점
  • refs 감는 데 시간이 걸린다
  • 단점:refs에 연루된 문제


    예를 들어 상술한 상황에서 PopOver와 조합된 상황에서refs의 문제가 발생한다
    <Popover>
      <PopoverTrigger>
        <RoundedOutlineButton>
      </PopoverTrigger>
      <PopoverContent>
        <PopoverHeader>Confirmation!</PopoverHeader>
        <PopoverBody>Are you sure you want to have that milkshake?</PopoverBody>
      </PopoverContent>
    </Popover >
    
    
    Warning: Function components cannot be given refs. 
    Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
    
    이기 때문에ref 같은 것을 사용하려면 사용해야 한다forwardRef
    import { forwardRef } from '@chakra-ui/react'
    
    // before
    // const RoundedOutlineButton: FC<ButtonProps> = (props) => { 
    
    // after
    const RoundedOutlineButton = forwardRef<ButtonProps, "button">((props, ref) => { 
      return <Button
        variant="outline"
        borderStyle="solid"
        borderWidth="2px"
        rounded="full"
        ref={ref}
        px={10}
        py={5}
        letterSpacing="0.1em"
        {...props} />
    })
    
    React.forwardRef도 가능하지만 몰드chakra-ui의forwardRef를 사용한다면 TS라면 조금 더 즐거울 수 있어요.

    2. Theme로 전체를 바꾼다


    만약'이 사이트는 모두 양식을 바꾸고 양식을 바꿀 수 있다'는 조건이 충족된다면 theme 방법도 사용할 수 있다
    import { extendTheme } from '@chakra-ui/react'
    
    const providerTheme = extendTheme({
      components: {
        Button: {
          variants: {
            outline: {
              bg: "white",
              borderStyle: "solid",
              borderWidth: "2px",
              rounded: "full",
              px: 10,
              py: 5,
              letterSpacing: "0.1em",
            },
          }
        }
      }
    })
    
    <ChakraProvider theme={providerTheme}>
      <Button variant="outline" colorScheme="blue">Provider Theme</Button>
    </ChakraProvider>
    
  • 이점
  • 구성 요소를 사용하면 모두 변경할 수 있음
  • refs 주위를 괴롭히지 않아도 된다
  • 단점
  • 전 세계적이기 때문에 다른 영향을 미치는지 주의할 필요가 있다
  • theme를 관리하는 각오가 필요하다
  • 보면 거의 사생 CSS에 가까운 양날의 검을 지닌 수법이다.

    3. Theme를 새로운 variant으로 만들기


    2를 조금 더 연하게 해라.새로운 variant 만들기
    import { theme, extendTheme } from '@chakra-ui/react'
    
    const providerThemeAppendVariant = extendTheme({
      components: {
        Button: {
          variants: {
            customOutline: (props) => {
              return {
                ...theme.components.Button.variants.outline(props),
                bg: "white",
                borderStyle: "solid",
                borderWidth: "2px",
                rounded: "full",
                px: 10,
                py: 5,
                letterSpacing: "0.1em",
              }
            },
          }
        }
      }
    })
    
    <ChakraProvider theme={providerThemeAppendVariant}>
      <Button variant="customOutline" colorScheme="blue">Provider Custom variant Theme</Button>
    </ChakraProvider>
    
  • 이점
  • 기존 영향 제거
  • refs 주위를 괴롭히지 않아도 된다
  • 단점
  • 하고 싶은 것보다 과장하기 쉽고 변경 범위도 넓다
  • 금형 주위에 약간의 우려가 있을 수 있음
  • 4. chakrafactory 기능으로 확장


    상당히 제한적이지만 factory에서 확장도 고려할 수 있다.
    const RoundedOutlineButton = chakra(Button, {
      baseStyle: {
        bg: "white",
        borderStyle: "solid",
        borderWidth: "2px",
        rounded: "full",
        px: 10,
        py: 5,
        letterSpacing: "0.1em",
      }
    })
    
    <RoundedOutlineButton variant="outline" colorScheme="blue">
      Factory Custom Button
    </RoundedOutlineButton>
    
  • 이점
  • refs 주위를 괴롭히지 않아도 된다
  • 단점
  • props를 얻을 수 없기 때문에 확장성이 매우 얇다
  • 기존의 variant와 겹치는 것처럼 뇌가 터진다
  • 프로퍼스가 얻지 못하는 것은 상당히 치명적인 부분이기 때문에 이 수법은 거의 사용할 수 없을 가능성이 있다.

    2021/06/20 추기


    v1.7.0부터factory의baseStyle도 함수를 제공함으로써props[1]를 획득할 수 있습니다
    const RoundedOutlineButton = chakra(Button, {
      baseStyle: (props) => {
        return {
          bg: props.bg,
          borderWidth: "2px",
          rounded: "full",
          px: 10,
          py: 5,
          letterSpacing: "0.1em",
        }
      }
    })
    
    
    더미도 얻을 수 있으니까 그럴 수도 있지
    const RoundedOutlineButton = chakra(Button, {
      baseStyle: ({ theme, ...props }) => {
        return {
          ...theme.components.Button.variants.outline(props),
          // borderStyle: "solid",
          borderWidth: "2px",
          rounded: "full",
          px: 10,
          py: 5,
          letterSpacing: "0.1em",
        }
      }
    })
    
    또한, 형식적으로 잘 대응하지는 않지만, 아래와 같이 CSS 이외의 props도 전달되기 때문에 colorScheme그런 것도 이용할 수 있다
    const RoundedOutlineButton = chakra(Button, {
      baseStyle: (props) => {
        // @ts-ignore
        const { colorScheme } = props
        return {
          bg: `white`,
          color: `${colorScheme}.600`,
          borderColor: `${colorScheme}.600`,
          borderStyle: "solid",
          borderWidth: "2px",
          rounded: "full",
          px: 10,
          py: 5,
          letterSpacing: "0.1em",
          _hover: {
            bg: `${colorScheme}.50`
          }
        }
      }
    })
    

    결론


    기본적으로 1입니다. forwardRef에 주의하는 것이 좋습니다.
    각오가 있다면 아마도
    각주
    PR은 던지자마자 통과했어요.https://github.com/chakra-ui/chakra-ui/releases/tag/%40chakra-ui%2Fsystem%401.7.0 ↩︎

    좋은 웹페이지 즐겨찾기