본문 바로가기
Books/러닝 리액트 ✔️

[Learning React] 6장 - 리액트 상태 관리

by Aaron-Kim 2022. 2. 1.

6.1 별점 컴포넌트 만들기

  - react-icons (npm 라이브러리)

6.2 useState 훅

  - 훅스에는 컴포넌트 트리와는 별도로 재사용 가능한 코드 로직이 들어있음

  - useState 훅: 상태를 리액트 컴포넌트에 추가하고 싶을 때 사용

    - React 패키지에 들어있음

    - 배열 반환

    - 배열의 첫 번째 값은 상태 변수

    - 배열의 두 번째 값은 상태 값을 변경할 때 쓸 수 있는 함수

    - useState 함수에 전달하는 값은 상태 변수의 default 값

    - 훅이 걸린 데이터가 변경되면 데이터에 대한 훅이 걸린 컴포넌트에 새 값을 전달하면서

      컴포넌트 re-rendering 일어남

6.3 재사용성을 높이기 위한 리팩터링

  - style 프로퍼티; CSS 스타일을 엘리먼트에 추가 가능

    - JSX에서 이중 중괄호 이용

6.4 컴포넌트 트리 안의 상태

  - 상태를 컴포넌트 트리의 아래로 내려보내기

    - 루트 App 컴포넌트에만 상태 저장해서 자식 컴포넌트들에게 프롭으로 전달

    - 순수 컴포넌트; 상태가 없어서 항상 같은 프롭에 대해 같은 UI를 렌더링 해주는 컴포넌트

  - 상호작용을 컴포넌트 트리 위쪽으로 전달하기

    - 자식 컴포넌트에 대해 벌어진 상호작용을 수집해서 트리의 위로 올려보내어 상태가 저장된 루트에 도착

    - 요소 제거하고 싶을 때 filter 함수 이용

    - 프롭을 통해 데이터를 컴포넌트 트리로 내려보내는 것과 비슷하게,

      사용자 상호작용은 함수 프로퍼티를 통해 데이터와 함께 트리 위로 전달됨

6.5 폼 만들기

  - 참조 사용하기

    - 폼 컴포넌트; ref라는 리액트 기능을 사용해 직접 DOM에 접근 가능

      - ref; 리액트에서 컴포넌트의 생명주기 값을 저장하는 객체

    - useRef 훅

      - input 엘리먼트에 ref 속성 추가

      - DOM 엘리먼트를 직접 참조하는 ref 객체에 대한 current 필드 생성

      - 리액트 밖에서 폼에 접근해 폼에 속한 입력 값 처리하고 싶을 때 사용

      - uncontrolled 컴포넌트, 명령형 코드

 

import React, { useRef } from 'react';

export default function AddColorForm({ onNewColor = (f) => f }) {
  const txtTitle = useRef();
  const hexColor = useRef();

  const submit = (e) => {
    e.preventDefault();
    const title = txtTitle.current.value;
    const color = hexColor.current.value;
    onNewColor(title, color);
    txtTitle.current.value = '';
    hexColor.current.value = '';
  };

  return (
    <form onSubmit={submit}>
      <input ref={txtTitle} type="text" placeholder="color title..." required />
      <input ref={hexColor} type="color" required />
      <button>ADD</button>
    </form>
  );
}

 

  - 제어가 되는 컴포넌트

    - controlled 컴포넌트에서는 폼 값을 DOM이 아니라 리액트로 관리함

    - useRef 사용할 필요 없음, 명령형 코드 작성할 필요 없음

    - useRef 대신 useState 이용

 

import React, { useState } from 'react';

export default function AddColorForm({ onNewColor = (f) => f }) {
  const [title, setTitle] = useState('');
  const [color, setColor] = useState('#000000');

  const submit = (e) => {
    e.preventDefault();
    onNewColor(title, color);
    setTitle('');
    setColor('');
  };

  return (
    <form onSubmit={submit}>
      <input
        value={title}
        onChange={(event) => setTitle(event.target.value)}
        type="text"
        placeholder="color title..."
        required
      />
      <input
        value={color}
        onChange={(event) => setColor(event.target.value)}
        type="color"
        required
      />
      <button>ADD</button>
    </form>
  );
}

 

  - 커스텀 훅 만들기

 

import { useState } from 'react';

export const useInput = (initialValue) => {
  const [value, setValue] = useState(initialValue);
  return [
    { value, onChange: (e) => setValue(e.target.value) },
    () => setValue(initialValue),
  ];
};

 

import React, { useState } from 'react';
import { useInput } from '../hooks/useInput';

export default function AddColorForm({ onNewColor = (f) => f }) {
  const [titleProps, resetTitle] = useInput('');
  const [colorProps, resetColor] = useInput('#000000');

  const submit = (e) => {
    e.preventDefault();
    onNewColor(titleProps.value, colorProps.value);
    resetTitle('');
    resetColor('');
  };

  return (
    <form onSubmit={submit}>
      <input
        {...titleProps}
        type="text"
        placeholder="color title..."
        required
      />
      <input {...colorProps} type="color" required />
      <button>ADD</button>
    </form>
  );
}

 

  - 색을 상태에 추가하기

 

import React, { useState } from 'react';
import colorData from './data/color-data';
import ColorList from './components/ColorList';
import AddColorForm from './components/AddColorForm';
import { v4 } from 'uuid';

function App() {
  const [colors, setColors] = useState(colorData);
  return (
    <>
      <AddColorForm
        onNewColor={(title, color) => {
          const newColors = [
            ...colors,
            {
              id: v4(),
              rating: 0,
              title,
              color,
            },
          ];
          setColors(newColors);
        }}
      />
      <ColorList
        colors={colors}
        onRemoveColor={(id) => {
          const newColors = colors.filter((color) => color.id !== id);
          setColors(newColors);
        }}
        onRateColor={(id, rating) => {
          const newColors = colors.map((color) =>
            color.id === id ? { ...color, rating } : color
          );
          setColors(newColors);
        }}
      />
    </>
  );
}

export default App;

 

6.6 리액트 콘텍스트

  - 콘텍스트에 색 넣기

    - Context Provider에게 데이터를 넣고, Provider를 컴포넌트 트리에 추가

    - createContext 함수를 이용하여 새로운 Context 객체 생성

      - Context 객체에는 Context Provider와 Context Consumer 2가지 컴포넌트가 들어 있음

  - useContext를 통해 색 얻기

  - 상태가 있는 콘텍스트 프로바이더

    - Context Provider는 객체를 Context에 넣을 수 있음

    - Context Provider 자체로는 Context 상에 들어 있는 값 변경 불가

    - Context Provider를 렌더링하는 상태가 있는 컴포넌트로 만들기 => Custom Provider

 

import React, { createContext, useState } from 'react';
import colorData from './data/color-data';
import { v4 } from 'uuid';

const ColorContext = createContext();

export default function ColorProvider({ children }) {
  const [colors, setColors] = useState(colorData);

  const addColor = (title, color) => {
    setColors([
      ...colors,
      {
        id: v4(),
        rating: 0,
        title,
        color,
      },
    ]);
  };

  const removeColor = (id) =>
    setColors(colors.filter((color) => color.id !== id));

  const rateColor = (id, rating) =>
    setColors(
      colors.map((color) => (color.id === id ? { ...color, rating } : color))
    );

  return (
    <ColorContext.Provider value={{ colors, addColor, removeColor, rateColor }}>
      {children}
    </ColorContext.Provider>
  );
}

 

  - 콘텍스트와 커스텀 훅

 

const ColorContext = createContext();
export const useColors = () => useContext(ColorContext);

[Source Code] 러닝 리액트 Ch06. 리액트 상태 관리

반응형

댓글