useState

홍준섭·2023년 2월 25일

react

목록 보기
4/29

useState

useState는 상태를 관리해주는 hook이다.

import React, {useState} from 'react';

//useState 예시
const Counter = () =>{
    const[value,setValue] = useState(0);
    return(
        <div>
          <p>
            {value}
          </p>
          <button onClick={()=>setValue(value+1)}>+1</button>
          <button onClick={()=>setValue(value-1)}>-1</button>
        </div>);
};

export default Counter;
		

이전 state를 기반으로 state 업데이트

set 함수를 사용하면 React는 다음 상태를 저장하고 새 값으로 구성 요소를 다시 렌더링하고 UI를 업데이트 한다.
그러나 set 함수를 호출해도 이미 실행 중인 코드의 현재 상태는 변경 되지 않는다.

function handleClick(){
  // 이렇게 setAge를 3번 사용하는 경우 age 값이 실행 중인 코드에서는 변하지 않으므로 결국 age 값은 1만큼 증가한다
  setAge(age+1)
  setAge(age+1)
  setAge(age+1)
}
function handleClick(){
// 상태 대신 업데이터 함수를 전달 하면 이러한 문제를 해결 할 수 있다. 
  setAge(a => a+1);
  setAge(a => a+1);
  setAge(a => a+1);
}

객체와 배열 업데이트

React에서 state는 읽기 전용으로 간주되므로 기존 객체를 변경하는 대신 교체해야 한다.

import { useState } from 'react';

export default function Form() {
  const [form, setForm] = useState({
    firstName: 'Barbara',
    lastName: 'Hepworth',
    email: 'bhepworth@sculpture.com',
  });

  return (
    <>
      <label>
        First name:
        <input
          value={form.firstName}
          onChange={e => {
            setForm({
              ...form,
              firstName: e.target.value
            });
          }}
        />
      </label>
      <label>
        Last name:
        <input
          value={form.lastName}
          onChange={e => {
            setForm({
              ...form,
              lastName: e.target.value
            });
          }}
        />
      </label>
      <label>
        Email:
        <input
          value={form.email}
          onChange={e => {
            setForm({
              ...form,
              email: e.target.value
            });
          }}
        />
      </label>
      <p>
        {form.firstName}{' '}
        {form.lastName}{' '}
        ({form.email})
      </p>
    </>
  );
}
import { useState } from 'react';
import AddTodo from './AddTodo.js';
import TaskList from './TaskList.js';

let nextId = 3;
const initialTodos = [
  { id: 0, title: 'Buy milk', done: true },
  { id: 1, title: 'Eat tacos', done: false },
  { id: 2, title: 'Brew tea', done: false },
];

export default function TaskApp() {
  const [todos, setTodos] = useState(initialTodos);

  function handleAddTodo(title) {
    setTodos([
      ...todos,
      {
        id: nextId++,
        title: title,
        done: false
      }
    ]);
  }

  function handleChangeTodo(nextTodo) {
    setTodos(todos.map(t => {
      if (t.id === nextTodo.id) {
        return nextTodo;
      } else {
        return t;
      }
    }));
  }

  function handleDeleteTodo(todoId) {
    setTodos(
      todos.filter(t => t.id !== todoId)
    );
  }

  return (
    <>
      <AddTodo
        onAddTodo={handleAddTodo}
      />
      <TaskList
        todos={todos}
        onChangeTodo={handleChangeTodo}
        onDeleteTodo={handleDeleteTodo}
      />
    </>
  );
}

초기 state 재생성 방지

React는 초기 상태를 한번 저장하고 다음 렌더링에서는 무시한다

// 이렇게 사용시 createInitalTodos()는 초기 렌더링에만 사용되지만 여전히 모든 렌더링에서 이 함수를 호출하고 있다. 그렇기에 큰 배열을 만들거나 비용이 많이 드는 계산을 수행하는 경우 낭비일 수 있다.
function TodoList(){
  const [todos, setTodos] = useState(createInitalTodos());
}
// 그렇기에 이와 같이 초기화 함수를 전달하여 초기화 중에만 함수를 호출 하도록 한다.
function TodoList(){
  const [todos,setTodos] = useState(createInitialTodos);
}

key로 state 재설정

key attribute는 일반적으로 목록을 렌더링할 때 사용된다. 그러나 키는 목록만을 위한 것이 아니다. 키를 사용하여 React가 모든 구성요소를 구별하도록 만들 수 있다. 기본적으로 React는 부모 내의 순서를 사용하여 구성 요소를 식별한다. 그러나 키를 사용하면 이것이 첫 번째 카운터나 두번째 카운터가 아니라 특정 카운터임을 React에 알릴 수 있다.

import { useState } from 'react';

export default function App() {
  const [version, setVersion] = useState(0);

  function handleReset() {
    setVersion(version + 1);
  }

  return (
    <>
      <button onClick={handleReset}>Reset</button>
      <Form key={version} />
    </>
  );
}

function Form() {
  const [name, setName] = useState('Taylor');

  return (
    <>
      <input
        value={name}
        onChange={e => setName(e.target.value)}
      />
      <p>Hello, {name}.</p>

이전 렌더링 정보 저장

import { useState } from 'react';

export default function CountLabel({ count }) {
  const [prevCount, setPrevCount] = useState(count);
  const [trend, setTrend] = useState(null);
  if (prevCount !== count) {
    setPrevCount(count);
    setTrend(count > prevCount ? 'increasing' : 'decreasing');
  }
  return (
    <>
      <h1>{count}</h1>
      {trend && <p>The count is {trend}</p>}
    </>
  );
}
profile
개발 공부중입니다

0개의 댓글