4일차(3.1~3.3)

01. 컴포넌트 생성

GlobalStyle- 활용 검색

// App.js

const GlobalStyle = createGlobalStyle`
  body {
    background-color: #e9ecef;
  }
`
// index.css에 추가하지 않고 전역 스타일을 설정할 수 있다

function App() {
  return (
    <div className='App'>
      <GlobalStyle />
      <TodoTemplate>
        <TodoHead />
        <TodoList />
        <TodoCreate />
      </TodoTemplate>
    </div>
  )
}

전부 styledComponent로 만들지 않고, 자식에게 className을 주어서 상속문법으로 적용시킬 수도 있다
조건부 스타일링을 할 필요가 없고, 기능적으로도 크게 중요하지 않은 내용이라면 CSS Selector 를 사용하는 것도 좋은 방법이다

const TodoHeadBlock = styled.div`
  padding-top: 48px;
  padding-left: 32px;
  padding-right: 32px;
  padding-bottom: 24px;
  border-bottom: 1px solid #e9ecef;
  h1 {
    margin: 0;
    font-size: 36px;
    color: #343a40;
  }
  .day {
    margin-top: 4px;
    color: #868e96;
    font-size: 21px;
  }
  .tasks-left {
    color: #20c997;
    font-size: 18px;
    margin-top: 40px;
    font-weight: bold;
  }
`

컴포넌트 셀렉터

const TodoItemBlock = styled.div`
  display: flex;
  align-items: center;
  padding-top: 12px;
  padding-bottom: 12px;
  &:hover {
    ${Remove} { // 컴포넌트 셀렉터
      display: initial;
    }
  }
`

리액트 아이콘 라이브러리

import { MdDone, MdDelete } from 'react-icons/md'

정적인 속성들과 동적인 속성을 구분해서 따로 작성하는게 더 깔끔한 것 같다

const CircleButton = styled.button`
  background: #38d9a9;
  &:hover {
    background: #63e6be;
  }
  &:active {
    background: #20c997;
  }

  z-index: 5;
  cursor: pointer;
  width: 80px;
  height: 80px;
  display: block;
  align-items: center;
  justify-content: center;
  font-size: 60px;
  position: absolute;
  left: 50%;
  bottom: 0px;
  transform: translate(-50%, 50%);
  color: white;
  border-radius: 50%;
  border: none;
  outline: none;
  display: flex;
  align-items: center;
  justify-content: center;

  transition: 0.125s all ease-in;
 
  ${(props) =>
    props.open &&
    css`
      background: #ff6b6b;
      &:hover {
        background: #ff8787;
      }
      &:active {
        background: #fa5252;
      }
      transform: translate(-50%, 50%) rotate(45deg);
    `}
`

02. Context API 를 활용한 상태 관리

  1. context.js파일을 만든다
  2. 초기데이터를 불러오고 reducer함수를 만들어준다
  3. state와 함수들 각각의 context를 만든다
  4. Provider컴포넌트를 만든다
  • 인자로 children가 들어가는데, 값을 사용할 범위를 지정해주는 것
  • useReducer를 사용해 값을 꺼내온다(useState를 사용할 수도 있음)
  • 반환값은 인자를 감싼 각 값이 전달된 context.Provider컴포넌트들이다
  1. context파일 안에서 useContext사용해 직접 값 할당을 받은 후 내보내서 사용할 수도 있다
  2. App컴포넌트에서 Provider컴포넌트를 import해서 사용할 범위만큼 컴포넌트들을 감싸준다

03. 기능 구현하기

Date 의 toLocaleString

첫번째 인자: 사용할 언어

두번째 인자: 어떤 값을 어떤 형식으로 가져올 건지에 대한 객체 형식의 옵션

  const today = new Date()

  // 년, 월, 일
  const dateString = today.toLocaleDateString('ko-KR', {
    year: 'numeric',
    month: 'long',
    day: 'numeric',
  })

  // 요일
  const dayName = today.toLocaleDateString('ko-KR', { weekday: 'long' })

useReducer의 dispatch

정보를 받아 해당하는 setState를 일으켜주는 함수

const dispatch = useTodoDispatch()
  const onToggle = () => dispatch({ type: 'TOGGLE', id }) // 정보를 받아 setState를 일으켜주는 함수
  const onRemove = () => dispatch({ type: 'REMOVE', id })

useRef 전역 변수의 값 변경

const onSubmit = (e) => {
    e.preventDefault()
    dispatch({
      type: 'CREATE',
      todo: { id: nextId.current, text: value, done: false },
    })
    setValue('') //제출하고 난 뒤, input값을 비워줌
    setOpen(false) // 제출하고 난 뒤, input창을 닫아줌
    nextId.current += 1 // 전역 변수인 nextId의 값을 +1 해줌 - 전역 변수이기 때문에 가능한듯(setter함수를 안쓰기 때문에)
  }

여러 컴포넌트를 조건부 렌더링하는 법

return (
    <>
      {open && (
        <InsertFormPositioner>
          <InsertForm onSubmit={onSubmit}>
            <Input
              autoFocus
              placeholder='할 일을 입력 후, Enter를 누르세요'
              onChange={onChange}
              value={value}
            />
          </InsertForm>
        </InsertFormPositioner>
      )}
      <CircleButton onClick={onToggle} open={open}>
        <MdAdd />
      </CircleButton>
    </>
  )

이해 안 가는 부분

그리고 맨 마지막 줄에서는 React.memo 로 감싸주었는데요, 이렇게 함으로써 TodoContext 에서 관리하고 있는 state 가 바뀔 때 때 TodoCreate 의 불필요한 리렌더링을 방지 할 수 있습니다. 만약 우리가 Context 를 하나만 만들었다면 이런 최적화를 하지 못하게 됩니다.


알게된 점

  • emotion에서 css쓰는 법

  • outline - 레이아웃에 영향 안줌
  • autoFocus - 속성으로 넣어주면 자동으로 focus
  • provider는 최소한만 사용, 너무 겹쳐서쓰면 렌더링문제가 발생
    → 상태가 담겨있는 것 만으로도 사용을 안했어도 상태가 바뀌면 리렌더링이 된다?

출처 https://react.vlpt.us/

좋은 웹페이지 즐겨찾기