고차 컴포넌트 (Higher-Order Components) - React with TS

sangwoo noh·2022년 2월 21일
0

ReactJS

목록 보기
5/16
post-thumbnail

preview

  1. 고차 함수랑 개념이 같음
  2. 함수 이름은 with로 시작하는것이 관습

authontication처리를 HOC로 해보자

  1. HOC pattern with Typescript
    withAuthCheck.tsx
import { useEffect, ComponentType } from 'react'
import { useSelector } from 'react-redux'
import { RootState } from 'store/store'
import notify from 'components/utils/toast'
import { useNavigate } from 'react-router-dom'
interface WrappedProps {}

const withAuthCheck = <P extends WrappedProps>(

  // wrappedComponent에서 전달 받은 props를 HOC에서 사용할 수 있다
  WrappedComponent: ComponentType<P>,
) => {
  const Component = (props: P) => {
    const isLogin = useSelector((state: RootState) => state.users.isLogin)
    const navigate = useNavigate()
    useEffect(() => {
      if (!isLogin) {
        notify({
          title: '잘못된 접근입니다.',
          type: 'error',
        })
        navigate('/')
      }
    }, [isLogin, navigate])

    return <WrappedComponent {...props} />
  }
  return Component
}

export default withAuthCheck
  1. 사용법
    DashboardLayout.tsx(로그인해야지만 접근 가능한 path)
import React, { useState } from 'react'
import { Outlet } from 'react-router-dom'
import { styled } from '@mui/material/styles'
import DashboardSidebar from './DashboardSidebar'
import withAuthCheck from 'components/HOC/withAuthCheck'

const APP_BAR_MOBILE = 64
const APP_BAR_DESKTOP = 92

const RootStyle = styled('div')({
  display: 'flex',
  minHeight: '100%',
  overflow: 'hidden',
})

const MainStyle = styled('div')(({ theme }) => ({
  flexGrow: 1,
  overflow: 'auto',
  minHeight: '100%',
  paddingTop: APP_BAR_MOBILE + 24,
  paddingBottom: theme.spacing(10),
  [theme.breakpoints.up('lg')]: {
    paddingTop: APP_BAR_DESKTOP + 24,
    paddingLeft: theme.spacing(2),
    paddingRight: theme.spacing(2),
  },
}))

const DashboardLayout = () => {
  const [open, setOpen] = useState(false)
  return (
    <RootStyle>
      {/* <DashboardNavbar onOpenSidebar={() => setOpen(true)} /> */}
      <DashboardSidebar
        isOpensidebar={open}
        onCloseSidebar={() => setOpen(false)}
      />
      <MainStyle>
        <Outlet />
      </MainStyle>
    </RootStyle>
  )
}
export default withAuthCheck(DashboardLayout)
profile
하기로 했으면 하자

0개의 댓글