[React] The State Hooks

윤남주·2022년 1월 17일
1

리액트 부수기

목록 보기
12/21
post-thumbnail

해당 포스트는 코드아카데미의 React 101 강의의 필기입니다.


Hooks

클래스 컴포넌트의 단점이 부각되자 함수 컴포넌트에서도 여러가지 동작을 할 수 있도록 Hooks를 추가함
➡️ state, lifecycle 기능을 함수형 컴포넌트에서도 이용할 수 있도록 해주는 장치

  • useState()
  • useEffect()
  • useContect()
  • useReducer()
  • useRef()

참고 : https://reactjs.org/docs/hooks-reference.html


State Hook

Importing State Hook

named export여서 { } 사이에 가져와야함

import React, { useState } from 'react';

react 라이브러리에서 React{ useState }를 가져온다!

useState()

: 리액트 라이브러리에 정의된 자바스크립트 Function
리턴값으로 두개의 값을 담은 배열을 도출함

  • current state : 현재 상태
  • state setter : 상태를 변경하는 함수

const [toggle, setToggle] = useState();
식으로 정의해야 두 값에 대한 변수명을 줄 수 있음

현재 렌더링에서 변경되어야하는 값이 있다면 setter 함수를 호출하여 상태 변경을 하면 됨.
상태 변경이 일어나면 자동으로 re-rendering이 됨.

예시 컴포넌트

import React, { useState } from 'react';

export default function ColorPicker() {
  const [color, setColor] = useState();
  const divStyle = {backgroundColor: color};

  return (
    <div style={divStyle}>
      <p>The color is {color}</p>
      <button onClick={() => setColor('Aquamarine')}>
        Aquamarine
      </button>
      <button onClick={() => setColor('BlueViolet')}>
        BlueViolet
      </button>
      <button onClick={() => setColor('Chartreuse')}>
        Chartreuse
      </button>
      <button onClick={() => setColor('CornflowerBlue')}>
        CornflowerBlue
      </button>
    </div>
  );
}

Initialize State

State Hook는 모든 원시 자료형과 배열, 객체를 다룰 수 있음
(예. boolean → toggle between true / false)

처음 렌더링 시 초기값을 지정하고 싶다면 useState(여기!)에 넣으면 됨

  1. 첫 렌더링 시 초기값으로 사용됨
  2. state setter 함수가 사용되면 초기값은 무시되고 새로운 값이 들어옴
  3. 컴포넌트가 어떠한 이유로 재렌더링 되면 바로 직전의 값을 사용함

초기값을 주지 않으면 undefined로 렌더링 함

개발자간 커뮤니케이션을 위해 초기값을 세팅하지 않겠다는 의사를 표시하고 싶을 경우 null을 넣자!

Initial color를 보라색으로 설정할 경우

const [color, setColor] = useState('Purple');

JSX 밖에서 State Setter 사용하기

JSX요소에 attribute로 준 이벤트리스너에 인라인으로 state setter 함수를 사용해도 좋지만, 따로 더 복잡한 로직을 가진 함수를 만들어 불러오는 것도 좋음.

const handleChange = (event) => {
  const newEmail = event.target.value;
  setEmail(newEmail);
}

더 짧게는 구조분해할당을 이용할 수 있음

const handleChange = ({ target }) => {
  setEmail(target.value);
}

그리고 만든 함수를 jsx요소에 추가한다

return <input type="text" onChange={handleChange} />

setter 사용 시 기존 값에서 변경 주기

콜백함수 형태로 하는 것이 가장 안전하다

const [count, setCount] = useState(0);
const increment = () => setCount(prevCount => prevCount + 1);

// 혹은
setCount(prevCount => prevCount + 1);

// 덜 좋은 예
setCount(count + 1);

state로 array 다루기

static array
그냥 값을 가지고 있고, 변하지 않는 배열의 경우 함수 컴포넌트 밖에 선언함.
변하지 않으니 재렌더링 시 포함될 필요 없음.

dynamic array
변하는 값을 가진 배열의 경우 state로 관리함.
값을 추가하는 경우 push하지 않고, spear syntax를 사용해 이전의 값을 복사한 후 값을 추가 : setState(prev => [newVal, ...prev])

array methods
.includes()
.filter()
.map()
등의 배열을 다루는 메소드를 많이 사용함
예. includes - 참/거짓 값 도출할 경우
filter - 특정 값을 없앨 경우
map - 특정 배열로 비슷한 요소들을 렌더링할 경우


Groceries 리스트에 추가 + 삭제 (index로)

function GroceryCart() {
  const [cart, setCart] = useState([]);

  const addItem = (item) => {
    setCart(prev => [item, ...prev]);
   };

  const removeItem = (targetIndex) => {
    setCart(prev => prev.filter((item, index) => index !== targetIndex));
  };

  return (
    <div>
      <h1>Grocery Cart</h1>
      <ul>
        {cart.map((item, index) => (
          <li onClick={() => removeItem(index)} key={index}>
            {item}
          </li>
        ))}
      </ul>
      <h2>Produce</h2>
      <ItemList items={produce} onItemClick={addItem} />
      <h2>Pantry Items</h2>
      <ItemList items={pantryItems} onItemClick={addItem} />
    </div>
  );
}

state로 object 다루기

export default function Login() {
  const [formState, setFormState] = useState({});
 
  const handleChange = ({ target }) => {
    const { name, value } = target;
    setFormState((prev) => ({
      ...prev,
      [name]: value
    }));
  };
 
  return (
    <form>
      <input
        value={formState.firstName}
        onChange={handleChange}
        name="firstName"
        type="text"
      />
      <input
        value={formState.password}
        onChange={handleChange}
        type="password"
        name="password"
      />
    </form>
  );
}
  • 먼저 formState는 빈 객체
  • handleChange() 함수는 event의 target을 argument로 받아 target에서 name값과 value값을 동일명의 변수에 넣음
  • setFormState를 통해 이전 객체에 [name]: value 꼴의 새 프로퍼티를 넣음 (spread syntax 사용)
  • ➡️ 결과적으로는 두 개의 프로퍼티가 들어가게 됨 (firstname과 password)

💡 <input>에는 보통 없는 name 속성을 추가하여 한 이벤트 핸들러로 두개의 인풋에 대응할 수 있음


💡 한 State에 너무 많은 정보를 넣으면, 이를 업데이트하는 함수를 정의할 때, 너무 복잡해질 수 있음 → 적당히 나누어 여러개의 State 사용

profile
Dig a little deeper

1개의 댓글

comment-user-thumbnail
2022년 11월 14일

☺️ 이런 글이 필요했는데!! 감사합니다!

답글 달기