[2024.05.27] TIL 27일차

김선민·2024년 5월 27일

[ 본캠프 27일차 기록 ]

🖥️ 오늘 공부한 내용 🖥️

#useState란?

  • 함수형 또는 클래스형 컴포넌트 내에서 state(상태)를 관리 및 변경할 수 있게 해주는 React 훅이다.
  • React에서 제공하는 다양한 ReactHooks 중에 하나로, 함수형 또는 클래스형 컴포넌트에서 로컬의 데이터 상태를 관리할 수 있게 만들어 주는 기능이다.
  • 초기 입력될 상태 값을 인자로 받아서 상태 값과 해당 상태를 업데이트하는 함수를 쌍으로 반환하게 된다.
  • 함수는 stateless다.
    • 일반 변수는 함수가 끝날 때 사라지기 때문에 useState를 통해서 함수형 컴포넌트 내에서 상태를 관리할 수 있게 해주는 것이다.

# useState(initialState)

1. 컴포넌트의 최상위 레벨에서 useState를 호출하여 state 변수를 선언한다.

	import { useState } from 'react';
    
    function MyComponent(){
    	const [ age, setAge ] = useState(28);
        const [ name, setName ] = useState('Taylor');
        // ...
  • initialState : 초기 상태 값을 지정한다.
    • 함수를 전달하면 초기화할 때 초기화 함수를 호출하고 반환 값을 초기 상태로 저장한다.
  • 정리
    • state에 해당하는 값은 첫 렌더링 때 useState의 파라미터로 받은 initialState를 통해 매칭한다.
    • 이후 setState를 통해 다른 값을 주입하여 상태를 업데이트하고 리렌더링한다.

2. 구조 분해 할당를 사용하여 [something, setSomething]과 같은 state 변수 이름을 지정한다.

  • 구조 분해 할당이란 객체를 여러 변수로 "압축해제"할 수 있는 특수 구문이다.
  • 함수에 전달할 때는 전부가 아닌 특정 요소나 속성만 필요할 수 있기 때문에,
    구조분해할당이 더 편리할 때가 있다.

[ 배열 해제 ]

  • 다음은 배열이 변수로 구조 해제되는 방법에 대한 예이다.
    let arr = ["John", "Smith"]

    // 구조 분해 할당
    // 배열 해체 할당을 사용하여 배열의 각 요소를 추출하여 변수에 할당한다.
    // sets firstName = arr[0]
    // and surname = arr[1]
    let [firstName, surname] = arr;

    alert(firstName); // John
    alert(surname);  // Smith

[ 쉼표를 사용하여 요소 무시 ]

  • 배열의 원하지 않는 요소는 추가 쉼표를 통해 제거할 수 있다.
    // second element is not needed
    let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

    alert( title ); // Consul

[ 오른쪽의 모든 반복 가능 항목과 함께 작동 ]

  • 실제로 배열뿐만 아니라 모든 반복 가능 항목과 함께 사용할 수 있다.
  • 내부적으로 구조분해 할당은 올바른 값을 반복하여 작동하기 때문에 다음과 같이 작동한다.
    let [a, b, c] = "abc"; // ["a", "b", "c"]
    let [one, two, three] = new Set([1, 2, 3]);

[ 왼쪽에 있는 항목에 할당 ]

  • 왼쪽에 있는 "할당 가능 항목"을 사용할 수 있다.
  • 예를 들어 객체 속성은 다음과 같다.
    • 예시 1 ) 아래 항목들은 할당 연산자 왼쪽에 위치하고 있고, 여기에 값을 할당할 수 있는 상태이다.
    • 예시 1 ) 왼쪽에 있는 할당 가능 항목은 user.nameuser.surname이다.
        let user = {};
        
       // 예시 1
        [user.name, user.surname] = "John Smith".split(' ');
        // "John Smith" 문자열을 공백을 기준으로 나눈 배열을 생성하고, 
        	배열 해체 할당을 통해 각 요소를 객체 user와 surname 프로퍼티에 할당한다. 

        alert(user.name); // John
        alert(user.surname); // Smith

[ .entries()를 사용한 반복 ]

  • 객체의 키와 값을 반복하기 위해 구조 분해와 함께 사용할 수 있다.
    let user = {
      name: "John",
      age: 30
    };

   // `Object.entries(user)를 사용하여 `user` 객체의 각 프로퍼티를 키-값 쌍의 배열로 반환
   // 배열 해체 할당을 사용하여 현재 요소의 각각의 요소를 `key`와 `value 변수에 할당
    for (let [key, value] of Object.entries(user)) {
      alert(`${key}:${value}`); // name:John, then age:30
    }
  • 유사 코드 (Map 반복)
    let user = new Map();
    user.set("name", "John");
    user.set("age", "30");

   // Map iterates as [key, value] pairs, very convenient for destructuring
    for (let [key, value] of user) {
      alert(`${key}:${value}`); // name:John, then age:30
    }

3. 매개 변수 : 함수에 전달되는 이름이 있는 변수

  • initialState는 초기에 state를 설정할 값이다.
    • 값은 모든 데이터 타입이 허용되지만, 함수에 대해서는 특별한 동작이 있다.
    • 이 인자는 초기 렌더링 이후에는 무시된다.

- 함수를 `initialState`로 전달하면 이를 초기화 함수로 취급한다. - 이 함수는 순수해야 하고, 인자를 받지 않아야 하며 반드시 어떤 값을 반환해야 한다. - React는 컴포넌트를 초기화할 때 함수를 호출하고 그 반환값을 초기 `state`로 저장한다.

4. 반환값

  • useState는 정확히 두 개의 값을 가진 배열을 반환한다.
    1. 첫 번째 렌더링 중에는 전달한 initialState와 일치한다
    2. state를 다른 값으로 업데이트하고, 리렌더링을 촉발할 수 있는 set(설정자) 함수이다.

5. 주의사항

  • useState는 훅이므로 컴포넌트 최상위 레벨이나 직접 만든 훅에서만 호출 가능하다.

    • 반복문이나 조건문 안에서는 호출할 수 없다.
    • 필요한 경우 새 컴포넌트를 추출하고 state를 그 안으로 옮기면 호출 할 수 있다.

  • Strict Mode에서 React는 의도치 않은 불순물을 찾기 위해 초기화 함수를 두번 호출한다.

    • 호출 중 하나의 결과는 무시된다.
    • 이는 개발 환경 전용 동작이며 실제 환경에는 영향을 미치지 않는다.

# setSomething(nextState)과 같은 set 함수

  • useState가 반환하는 set 함수를 사용하면 state를 다른 값으로 업데이트하고 리렌더링을 할 수 있다.
  • 다음 state를 직접 전달하거나, 이전 state로부터 계산하여 다음 state를 도출하는 함수를 전달할 수도 있다.
  const [name, setName] = useState('Edward');

  function handleClick() {
    setName('Taylor');
    setAge(a => a + 1);
   	
    // ...
  • 매개 변수
    • nextState는 state가 될 값이다.
      • 값은 모든 데이터 타입이 허용되지만, 함수에 대해서는 특별한 동작이 있다.

    • 함수를 nextState로 전달하면 업데이터 함수로 취급한다.
      • 이 함수는 순수해야 하고, 대기 중인 state를 유일한 인수로 사용해야 하며, 다음 state를 반환해야 한다.
      • React는 업데이터 함수를 대기열에 넣고 컴포넌트를 리렌더링한다.
      • 다음 렌더링 중에 React는 대기열에 있는 모든 업데이터를 이전 state에 적용하여 다음 state를 계산한다.

  • 매개 변수
  1. set 함수는 다음 렌더링에 대한 state 변수만 업데이트한다.
    set 함수를 호출한 후에도 state 변수에는 여전히 호출 전 화면에 있던 이전 값이 담겨 있다.

  2. 사용자가 제공한 새로운 값이 Object.is에 의해 현재 state와 동일하다고 판정되면, React는 컴포넌트와 그 자식들을 리렌더링하지 않는다.

  3. 모든 이벤트 핸들러가 실행되고 set 함수를 호출한 후에 화면을 업데이트한다.
    이렇게 하면 단일 이벤트 중에 여러 번 리렌더링 되는 것을 방지할 수 있다.

  4. 렌더링 도중 set 함수를 호출하는 것은 현재 렌더링 중인 컴포넌트 내에서만 허용된다.

# 사용법

# 컴포넌트에 state 추가하기

  • 컴포넌트 최상위 레벨에서 useState를 호출하여 하나 이상의 state 변수를 선언한다
  import { useState } from 'react';

  function MyComponent() {
    const [age, setAge] = useState(42);
    const [name, setName] = useState('Taylor');
    // ...
  1. 구조 분해 할당을 사용하여 [something, setSomething]과 같은 state 변수의 이름을 지정하는 것이 관례이다.
  2. useState는 정확히 두 개의 항목이 있는 배열을 반환합니다.
    • 이 state 변수의 현재 state로, 처음에 제공한 초기 state로 설정된다
    • 상호작용에 반응하여 다른 값으로 변경할 수 있는 set 함수이다.

화면의 내용을 업데이트하려면 다음 state로 set 함수를 호출한다 :

  function handleClick() {
    setName('Robin');
  }

# 예시 코드

1. Counter(number)

  import { useState } from 'react';

  export default function Counter() {
    const [count, setCount] = useState(0);

    function handleClick() {
      setCount(count + 1);
    }

    return (
      <button onClick={handleClick}>
        You pressed me {count} times
      </button>
    );
  }
  • count state 변수는 숫자를 받는다. 버튼을 클릭하면 숫자가 증가한다.

2. Text field(string)

  import { useState } from 'react';

  export default function MyInput() {
    const [text, setText] = useState('hello');

    function handleChange(e) {
      setText(e.target.value);
    }

    return (
      <>
        <input value={text} onChange={handleChange} />
        <p>You typed: {text}</p>
        <button onClick={() => setText('hello')}>
          Reset
        </button>
      </>
    );
  }
  • 예제에서 `text state 변수는 문자열을 받는다
  • input에 타이핑하면 handleChange는 input DOM 요소에서 최신 input 값을 읽고,
    setText를 호출하여 state를 업데이트한다

2. CheckBox(boolean)

  import { useState } from 'react';

  export default function MyCheckbox() {
    const [liked, setLiked] = useState(true);

    function handleChange(e) {
      setLiked(e.target.checked);
    }

    return (
      <>
        <label>
          <input
            type="checkbox"
            checked={liked}
            onChange={handleChange}
          />
          I liked this
        </label>
        <p>You {liked ? 'liked' : 'did not like'} this.</p>
      </>
    );
  }
  • 예제에서 liked state 변수는 boolean을 받는다.
  • input을 클릭하면 setLiked는 체크박스가 선택되어 있는 여부에 따라 liked state 변수를 업데이트 한다.
  • liked 변수는 체크박스 아래의 텍스트를 렌더링하는 데 사용된다.

2. Form (two variables)

  import { useState } from 'react';

  export default function Form() {
    const [name, setName] = useState('Taylor');
    const [age, setAge] = useState(42);

    return (
      <>
        <input
          value={name}
          onChange={e => setName(e.target.value)}
        />
        <button onClick={() => setAge(age + 1)}>
          Increment age
        </button>
        <p>Hello, {name}. You are {age}.</p>
      </>
    );
  }
  • 동일한 컴포넌트에 두개 이상의 state 변수를 선언할 수 있다
  • 각 state 변수는 완전히 독립적이다.
profile
웹 프론트엔드

0개의 댓글