데브코스 44일차 TIL : React [ContextAPI, react-router, 그 외 ]

te-ing·2021년 10월 18일
0
post-thumbnail

Context API

const TaskContext = createContext(); Context를 만드는 리액트함수

npm i uuid uuid를 쉽게 만들어주는 라이브러리
import { v4 } from "uuid" id: v4() 와 같이 사용

리액트는 데이터를 재활용하기 때문에 key값을 지정하지 않으면 버그가 발생하기 쉬우므로 꼭 key값을 지정해주어야 한다.

react-router

npm i react-router-dom , 아래와 같이 사용

import { Route, Switch } from 'react-router';
import { PostsPage } from './pages';

const App = () => {
  return (
    <div>
      <Switch>
        <Route path="/" exact>
          <h1>Home</h1>
        </Route>
        <Route path="/posts">
          <PostsPage />
        </Route>
      </Switch>
    </div>
  )
}

export default App;

exact를 붙이지 않으면 하위 페이지까지 포함한다.

import { Link } from "react-router-dom"

const Menu = () => {
  return <nav>
    <ul>
      <li>
        <Link to="/">Home</Link>
      </li>
      <li>
        <Link to="/posts">Posts</Link>
      </li>
    </ul>
  </nav>
}

export default Menu

Route Path에서 동적파라미터 받기

<Route path="/posts/:id">와 같이 :을 사용하면 동적파라미터를 받을 수 있다.

404NotFoundPage

<Route *path*="*"> <NotFoundPage /> </Route> 가장 아래에 두어야 함!

<input type="file" /> 에 style 적용하기

<input type="file" /> 에는 스타일을 적용할 수 없기 때문에 display:none 을 통해 가린 후 자식 button에 스타일을 적용해야 한다.

파일첨부 여부를 확인하기 위해서는 <Upload> {(file) => <button>{file ? file.name : 'Click me!'}</button>}</Upload> 과 같이 파일명으로 button의 값을 바꿔주는 방식을 사용할 수 있다.

feather

icon 라이브러리 feather npm install feather-icons

<i>태그

<i> 태그의 경우 기본적으로 inline 속성이기 때문에 아이콘으로 사용할 때 inline-block을 해줘야 크기가 정상적으로 작동한다.

styled에서의 조건식

(prop) ⇒ prop === 조건 ? true : false 와 같이 함수를 만들어서 백틱``을 통해 css 속성값으로 넣어주면 된다.

border-radius: ${({shape}) => shape === 'circle' ? '50%' : shape === 'round' ? '4px' : '0px'};

위와같이 조건이 여러개일 때에는 오브젝트를 선언하여 간단하게 만들 수 있다.

const ShapeToCssValue = {
  circle: '50%',
  round: '4px',
  square: '0px'
}
const AvatarWrapper = styled.div`
	border-radius: ${({ shape }) => ShapeToCssValue[shape]};
`

image를 불러올 때 itablity

background-color: lightgrey;
>  img { transition: opacity 0.2s ease-out; }

위와같이 불러올 때 투명도를 이용한 transition과 배경색을 넣어준다면, 있어빌리티하게 보여줄 수 있다.

toArray, isValidElement로 필요한 prop만 가져오는 법

import React from "react"

const AvatarGroup = ({ children, shape = 'circle', size= 70, ...props }) => {
  const avatars =React.Children.toArray(children)
  .filter(element => {
		if (React.isValidElement(element) && element.props.__TYPE === "Avatar") {
      return true;
    }
    return false
  })

offset()

요소의 위치를 조회하거나 지정하는 offset()메서드

이 메서드는 문서 기준 좌표로 위치를 측정하고, 이 x, y 좌표와 대응되는 left, top 프로퍼티를 가진 객체를 반환한다. 반대로 offset()메서드의 전달인자로 left, top프로퍼티가 있는 객체를 넘기면 요소를 해당 위치로 옮긴다. 이때 offset()메서드 내부에서 요소를 위치를 정하기 위해 CSS의 position속성을 지정한다. 출처: 양은냄비

useMemo, useCallback

Hooks

passive:true을 통한 성능향상

passive:true 설정시 e.preventDefault()를 체크하지 않아서 약간의 성능적 향상을 기대할 수 있다. ex) element.addEventListener('scroll', handleScroll, { passive: true })

requestAnimationFrame를 통한 성능향상

스크롤 이벤트시 리플로우 이벤트가 발생(리렌더링)되기 때문에 useRef대신 Raf(requestAnimationFrame)를 사용하면 약간의 성능향상을 기대할 수 있다.

import { useCallback, useRef, useState } from "react"

const useRafState = (initialState) => {
  const frame = useRef(0);
  const [state, setState] = useState(initialState)

  const setRafState = useCallback((value) => {
    cancelAnimationFrame(frame.current)

    frame.current = requestAnimationFrame(() => {
      setState(value)
    })
  }, [])

  return [state, setRafState]
}

export default useRafState

ResizeObserver

observer에서 감시하는 element의 크기가 변경되면 동작하는 함수

useReducer

useState가 넣어둔 값을 업데이트 했다면, useReducer는 업데이트한 항목을 내부적 로직으로 만들어 둘 수 있음

useReducer는 async await를 통한 네트워크 호출이 불가능하기 때문에 상태만 유지관리해야 한다.

import { useReducer } from "react"

const reducer = (state, action) => {
  switch (action.type) {
    case 'INIT_POST': {
      return action.payload
    }
    case 'ADD_POST': {
      return [...state, action.payload]
    }
    case 'DELETE_POST': {
      const payload = action.payload
      return state.filter(item => item.id !== payload.id)
    }
    default: {
      console.error('Wrong type!');
      break
    }
  }
}

const PostProvider = ({ children, initialPosts }) => {
  const [posts, dispatch] = useReducer(reducer, initialPosts || [])

  useEffect(() => {
    dispatch({ type: 'INIT_POST', payload: initialPosts || [] })
  }, [initialPosts])
}

컴포넌트는 순수할 수록 좋다

  • 사이드 이펙트를 걱정하지 않아도 된다.
  • 확장에 유연하다.
  • 테스트가 쉽다.

svg

적은용량으로 인한 빠른 실행, 크기를 줄였다 늘려도 이미지에 영향없음

경로별칭, 확장자 생략 alias

vue에서 module exports의 resolve에 alias: { '~': path.resolve(__dirname, 'src') } 를 추가했던 것처럼, react에서도 module.exports의 webpack에서 alias를 설정하여 경로를 설정할 수 있다.

import PostList from './components/domain/PostList''@components/domain/PostList'

// craco.config.js
const path = require('path')

module.exports = {
  webpack: {
    alias: {
      "@components": path.resolve(__dirname, "src/components"),
      "@hooks": path.resolve(__dirname, "src/hooks"),
      "@contexts": path.resolve(__dirname, "src/contexts"),
      "@pages": path.resolve(__dirname, "src/pages"),
    }
  }
}
profile
병아리 프론트엔드 개발자🐣

0개의 댓글