Frontend/react

[ react ] documentation useState ( 18.2.0 )

IT grow. 2024. 9. 10. 19:43
반응형

useState(initialState)

 

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

 

import { useState } from 'react';

function MyComponent() {
  const [age, setAge] = useState(28);
  const [name, setName] = useState('Taylor');
  const [todos, setTodos] = useState(() => createTodos());
  // ...


Parameters 

initialState : 초기 state 설정할 값입니다. 값은 모든 데이터 타입이 허용되지만 , 함수에 대해서는 특별한 동작이 있습니다. 이 인자는 초기 렌더링 이후에는 무시됩니다. 함수를 initialState로 전달하면 이를 초기화 함수로 취급합니다. 이 함수는 순수해야 하고 인자를 받지 않아야 하며 반드시 어떤 값을 반환해야 합니다. react는 컴포넌트를 초기화할 때 초기화 함수를 호출하고 , 그 반환값을 초기 state로 저장합니다.


Returns

useState 는 정확히 두 개의 값을 가진 배열을 반환합니다. 


1. 현재 state , 첫 번째 렌더링 중에는 전달한 initialState와 일치합니다.
2. state를 다른 값으로 업데이트하고 리렌더링을 촉발할 수 있는 set() 함수 입니다.

 

 

- useState는 훅이므로 컴포넌트의 최상위 레벨이나 직접 만든 훅에서만 호출할 수 있습니다. 반복문이나 조건문 안에서는호출할 수 없습니다. 필요한 경우 새 컴포넌트를 만들고 state를 그 안으로 옮기세요.

- Stric Mode 에서 react는 의도치 않은 불순물을 찾기 위해 초기화 함수를 두 번 호출합니다. 이는 개발 환경 전용 동작이며 상용 환경에는 영향을 미치지 않습니다. 초기화 함수가 순수하다면 동작에 영향을 미치지 않습니다. 호출 중 하나의 결과는 무시됩니다.

 

 

useState 가 반환하는 set 함수를 사용하면 state를 다른 값으로 업데이트하고 리렌더링을 촉발할 수 있습니다. 여기에는 다음 state를 직접 전달하거나 , 이전 state로부터 계산하여 다음 state를 도출하는 함수를 전달할 수도 있습니다.

 

const [name, setName] = useState('Edward');

function handleClick() {
  setName('Taylor');
  setAge(a => a + 1);
  // ...

 

Parameters

nextState : state가 될 값입니다. 값은 모든 데이터 타입이 허용되지만 , 함수에 대해서는 특별한 동작이 있습니다. 함수를 nextState로 전달하면 업데이터 함수로 취급됩니다. 이 함수는 순수해야 하고 , 대기 중인 state를 유일한 인수로 사용해야 하며 , 다음 state를 반환해야 합니다. react는 업데이터 함수를 대기열에 넣고 컴포넌트를 리렌더링 합니다. 다음 렌더링 중에 react는 대기열에 있는 모든 업데이터를 이전 state에 적용하여 다음 state를 계산합니다.

Returns 

set 함수는 반환값이 없습니다. set함수는 다음 렌더링에 대한 state 변수만 업데이트합니다. set 함수를 호출한 후에도 state 변수에는 여전히 호출 전 화면에 있던 이전 값이 담겨 있습니다.

사용자가 제공한 새로운 값이 Object.is 에 의해 현재 state와 동일하다고 판정되면 , react 는 컴포넌트와 그 자식들을 리렌더링하지 않습니다. 경우에 따라 react 가 자식을 건너뛰기 전에 컴포넌트를 호출해야 할 수도 있지만 , 코드에 영향을 미치지는 않습니다.

react 는 state 업데이트를 일괄처리합니다. 모든 이벤트 핸들러가 실행되고 set 함수를 호출한 후에 화면을 업데이트합니다. 이렇게 하면 단일 이벤트 중에  여러 번 리렌더링 되는 것을 방지할 수 있습니다. 드물지만 DOM에 접근하기 위해 react 가 화면을 더 일찍 업데이트 하도록 강제해야 하는 경우 , flushSync를 사용할 수 있습니다.

렌더링 도중 set 함수를 호출하는 것은 현재 렌더링 중인 컴포넌트 내에서만 허용됩니다. react는 해당 출력을 버리고 즉시 새로운 state로 다시 렌더링을 시도합니다. 이 패턴은 거의 필요하지 않지만 이전 렌더링의 정보를 저장하는 데 사용할 수 있습니다.

Stric Mode 에서 react 는 의도치않은 불순물을 찾기 위해 업데이터 함수를 두 번 호출합니다. 이는 개발환경 전용 동작이며 상용 환경에는 영향을 미치지 않습니다. 만약 업데이터 함수가 순수하다면 , 이것은 동작에 영향을 미치지 않습니다. 호출 중 하나의 결과는 무시됩니다.

 

 

set 함수를 호출해도 이미 실행중인 코드의 현재 state는 변경되지 않습니다.

 

function handleClick() {
  setName('Robin');
  console.log(name); // Still "Taylor"!
                     // 아직 "Taylor"입니다!
}

set 함수는 다음 렌더링에서 반환할 useState 에만 영향을 줍니다.

 

초기화 함수 전달 vs 초기 state 직접 전달 차이점

 

초기화 함수 전달하기 

import { useState } from 'react';

function createInitialTodos() {
  const initialTodos = [];
  for (let i = 0; i < 50; i++) {
    initialTodos.push({
      id: i,
      text: 'Item ' + (i + 1)
    });
  }
  return initialTodos;
}

export default function TodoList() {
  const [todos, setTodos] = useState(createInitialTodos);
  const [text, setText] = useState('');

  return (
    <>
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
      <button onClick={() => {
        setText('');
        setTodos([{
          id: todos.length,
          text: text
        }, ...todos]);
      }}>Add</button>
      <ul>
        {todos.map(item => (
          <li key={item.id}>
            {item.text}
          </li>
        ))}
      </ul>
    </>
  );
}

 

위 예제에서는 초기화 함수를 전달하므로 , createInitialTodos 함수는 초기화 중에만 실행됩니다. 컴포넌트가 리렌더링될 때 에는 실행되지 않습니다.

초기 state 직접 전달하기

import { useState } from 'react';

function createInitialTodos() {
  const initialTodos = [];
  for (let i = 0; i < 50; i++) {
    initialTodos.push({
      id: i,
      text: 'Item ' + (i + 1)
    });
  }
  return initialTodos;
}

export default function TodoList() {
  const [todos, setTodos] = useState(createInitialTodos());
  const [text, setText] = useState('');

  return (
    <>
      <input
        value={text}
        onChange={e => setText(e.target.value)}
      />
      <button onClick={() => {
        setText('');
        setTodos([{
          id: todos.length,
          text: text
        }, ...todos]);
      }}>Add</button>
      <ul>
        {todos.map(item => (
          <li key={item.id}>
            {item.text}
          </li>
        ))}
      </ul>
    </>
  );
}

 

위 예제에서는 초기화 함수를 전달하지 않으므로 , input 을 입력할 때와 같이 모든 렌더링에서 createInitialTodos 함수가 실행됩니다. 동작에 눈에 띄는 차이는 없지만 이 코드는 효율성이 떨어집니다.

 

 

반응형