[5주차] React 숙련 강의 내용 정리 (1) - styled Components, useState, useEffect, useContext

voyager 999·2024년 1월 24일

React

목록 보기
7/27

styled-components

npm install styled-components
yarn add styled-components

터미널 창에 명령어를 사용해서 styled-components 패키지를 설치하고, 문서에서 import하여 사용한다. 스타일 컴포넌트의 이름을 변수 선언하듯 선언하고, styled.div``;에서 백틱 안에 원하는 스타일링을 css 방식으로 작성해주면 된다.

스타일 코드에 if문, switch문, 삼항연산자 등을 사용하여 조건부 스타일링을 할 수 있다.
또한 props를 통해서 컴포넌트간 스타일링 정보를 전달할 수 있다.

전역 스타일링(Global Styles)

프로젝트 전체에 공통적으로 들어가는 스타일은 전역적으로 지정해주는 것이 좋다.

전역 스타일링용 새 jsx파일을 생성한 다음 해당 파일에서 createGlobalStyle을 import하면, 변수를 선언하여 전역 스타일링을 할 수 있다.

App.jsx에서 전역 스타일 파일을 import 해주고, return문 안에는 <GlobalStyle /> 요렇게 자식 컴포넌트로서 넣어주면 된다.

useState - 함수형 업데이트

setState의 ()안에 수정할 값을 직접 입력하는 것이 아니라 함수를 넣어 state를 업데이트 하는 방법.

아래의 두 방법 모두 동일한 결과가 출력된다.

/** 기존 방식 - setState 값을 직접 지정 */
<button 
   onClick={setNumber(number+1)}>
누르면 UP
</button>
/** 함수형 업데이트 */
<button
   onClick={() => {
      setNumber((currentNum) => {
         return currentNum + 1;
      });
   }}

누르면 UP
</button>

기존 방식으로는 여러번 setState를 하더라도 batch(일괄)처리 되기 때문에 동일한 명령을 하나로 모아 최종적으로 한 번만 실행하게 된다. 따라서 setState를 100번 하더라도 1번만 실행되고, 위의 코드에서 버튼을 클릭하면 숫자는 1씩 증가할 것이다.
반면 함수형 업데이트 방식setState 명령의 횟수만큼 순차적으로 실행하기 때문에, 3번 setState 하게 되면 버튼을 클릭 시 숫자는 3씩 증가하게 된다.


useEffect

리액트 프로젝트가 렌더링될 때 특정한 작업을 수행해야 할 때 설정하는 Hooks
캡쳐처럼 코드를 작성하면, input에 값을 입력할 때마다 setState되고, 따라서 console.log()가 계속 실행된다.

첫 화면 렌더링이 되었을 때만 console.log()를 실행하고 싶은 경우 의존성 배열(Dependency Array)이 필요하다.

  • 의존성 배열(Dependency Array):
    이 배열에 값을 넣으면 그 값이 바뀔 때만 useEffect를 실행한다. 이렇게 빈배열을 넣어주면, input에 의해 값이 얼마나 setState되든 간에 useEffect의 의존성 배열은 그냥 빈배열이기 때문에 console.log()는 최초 렌더링 시 1회만 실행된다.
    의존성 배열을 [value]로 설정해주면, input에 의해 setState될 때마다 useEffect가 실행된다.

  • Clean up:
    어떤 컴포넌트가 화면에서 사라졌을 때(unmount) 무언가를 실행하고 싶다면, useEffect에서 return문 함수 안에 실행하고자 하는 내용을 작성해주면 된다.


useRef

useRef으로 DOM 요소에 접근할 수 있다. react로부터 useRef를 import한 다음 선언하여 사용할 수 있다.

  • 저장공간으로 사용: 설정해 둔 ref값은 컴포넌트가 다시 렌더링되어도 unmount 되기 전까지는 값을 유지한다. 또한 state와는 다르게 ref값에 변화가 일어나도 렌더링이 일어나지 않기 때문에 리렌더링을 발생시키지 않는 값을 저장할 때 사용한다.

  • DOM 요소에 접근하는 방식으로 사용: 변수로 ref를 선언해 준 뒤, 접근하고 싶은 요소에 ref={변수명} 속성을 추가하여 연결해준다.

이렇게 하면 페이지가 렌더링 될 때 아이디 input에 자동으로 커서를 위치시킬 수 있다.


function App() {
  const idRef = useRef("");
  useEffect(() => idRef.current.focus(), []);
  return (
    <div>
      <div>
        아이디 : <input type="text" ref={idRef}/>
      </div>
      <div>
        비밀번호 : <input type="password"/>
      </div>
    </div>
  )
}

useEffect를 사용하여 아이디 input에 입력된 값이 10글자를 넘어가면 자동으로 비밀번호 input으로 커서가 이동하도록 할 수 있다.

import React, { useEffect, useRef, useState } from "react";

function App() {
  const idRef = useRef("");
  const pwRef = useRef("");
  const [id, setId] = useState("");

  useEffect(() => {
    if (id.length >= 10) {
      pwRef.current.focus();
    }
  }, [id]);

  return (
    <>
      <div>
        아이디 : <input type="text" value={id}
          onChange={(event) => setId(event.target.value)}
          ref={idRef} />
      </div>
      <div>
        비밀번호 : <input type="password" ref={pwRef} />
      </div>
    </>
  );
}

export default App;

useContext

부모 -> 자식 컴포넌트로 props 전달할 때 prop drilling현상으로 인해 오류 추적이 어려워지는 등의 문제점이 있을 수 있다.

이 때 useContext hook을 통해 전역 데이터를 관리할 수 있다.

  • CreateContext: context 생성
  1. context를 관리하는 js파일을 생성
  2. import { createContext } from "react"
  3. export const 파일명 = createContext(null);
  • Consumer: context 변화 감지

  • Provider: context 전달 (to 하위 컴포넌트)

  1. Provider 파일에 context 파일을 import
  2. Provider 파일의 return문 상위 div 자리에 context 태그 생성하여 context를 전달할 요소를 감싸줌
import React from "react";
import { familyContext } from "FamilyContext";
import Father from "Father";

function GrandFather() {
   const houseName = '파란집'
   const pocketMoney = 10000;
   
return (
   <FamilyContext.Provider 
      value={{
         houseName
         pocketMoney
      }}>
      <Father />
    </FamilyContext.Provider>
    );
}

export default GrandFather;
  1. 하위요소에서 useContext 이용하여 전역 데이터를 받아옴
function Child() {
   const data = useContext(FamilyContext);
   return (
   <div>
      우리집 이름은 {data.houseName}이에요.<br />
      용돈은 {data.pocketMoney}원 입니다.
   </div>
   )
}   

Provider에서 제공한 value가 달라지면 useContext를 사용하고 있는 모든 컴포넌트가 리렌더링 되므로 주의해야 한다.

0개의 댓글