본문 바로가기
Front-End/React

useState() 리액트 상태 관리 마스터하기

by 두두리안 2024. 2. 13.
728x90

1. useState 사용하지 않을때는?

const App = () => {
  // 배열선언
  const courseGoals = [
    { id: 'cg1', text: 'Finish the Course' },
    { id: 'cg2', text: 'Learn all about the Course Main Topic' },
    { id: 'cg3', text: 'Help other students in the Course Q&A' }
  ];

  // 배열안에 값 추가하는 이벤트 선언
  const addNewGoalHandler = newGoal => {
    courseGoals.push(newGoal);
    console.log(courseGoals);
  };

  return (
    <div className="course-goals">
      <h2>Course Goals</h2>
      <NewGoal onAddGoal={addNewGoalHandler} />
      <GoalList goals={courseGoals} />
    </div>
  );
};

NewGoal 컴포넌트 이벤트는 courseGoals 배열의 값을 추가해준다.

courseGoals 배열안에 값은 GoalList 컴포넌트에 전달해준다.

const NewGoal = props => {
  const addGoalHandler = event => {
    event.preventDefault();

    const newGoal = {
      id: Math.random().toString(),
      text: 'My new goal!'
    };

    props.onAddGoal(newGoal);
  };

  return (
    <form className="new-goal" onSubmit={addGoalHandler}>
      <input type="text" />
      <button type="submit">Add Goal</button>
    </form>
  );
};

form 안에 값이 submit 될때 props 전달해준다.

const GoalList = props => {
  return (
    <ul className="goal-list">
      {props.goals.map(goal => {
        return <li key={goal.id}>{goal.text}</li>;
      })}
    </ul>
  );
};

props 통해서 text 값을 리스트로 만들어준다.

배열에 값은 추가되지만 화면에는 렌더링이 되지않는다.

2. useState 이해하기

구성 요소가 데이터 변경에 반응할 수 있으므로 UI가 기본 데이터 모델과 동기화된 상태로 유지됩니다. 이는 사용자 상호 작용이나 기타 이벤트에 대한 응답으로 UI를 자주 업데이트해야 하는 동적 애플리케이션에 특히 유용하다.

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>
    </>
  );
}

input의 값이 변할때마다 text 값도 변하게 된다.

참고

useState – React

3. useState 적용하기

const App = () => {
  // useState 상태관리 선언
  const [courseGoals, setCourseGoals] = useState([
    { id: 'cg1', text: 'Finish the Course' },
    { id: 'cg2', text: 'Learn all about the Course Main Topic' },
    { id: 'cg3', text: 'Help other students in the Course Q&A' }
  ]);

  const addNewGoalHandler = newGoal => {
    // setCourseGoals(courseGoals.concat(newGoal));
    setCourseGoals(prevCourseGoals => prevCourseGoals.concat(newGoal));
  };

  return (
    <div className="course-goals">
      <h2>Course Goals</h2>
      <NewGoal onAddGoal={addNewGoalHandler} />
      <GoalList goals={courseGoals} />
    </div>
  );
};

useState 안에 배열을 넣어준다.

setCourseGoals 함수를 이용해서 이전 배열의 값과 들어온 배열을 값을 병합한다.

4. 양방향 바인딩하기

기존 프로젝트에서는 form 에서 submit 요청이 올때 My new Goal 값만 전달된다.

const addGoalHandler = event => {
    event.preventDefault();

    const newGoal = {
      id: Math.random().toString(),
      text: 'My new goal!'
    };

    props.onAddGoal(newGoal);
  };

input 값이 들어올때 그 값이 화면에 렌더링되게 적용해보자!

const NewGoal = props => {
  // enteredText 상태관리 선언
  const [enteredText, setEnteredText] = useState('');

  const addGoalHandler = event => {
    event.preventDefault();

    const newGoal = {
      id: Math.random().toString(),
      text: enteredText
    };

    setEnteredText('');

    props.onAddGoal(newGoal);
  };

  const textChangeHandler = event => {
    setEnteredText(event.target.value);
  };

  return (
    <form className="new-goal" onSubmit={addGoalHandler}>
      <input type="text" value={enteredText} onChange={textChangeHandler} />
      <button type="submit">Add Goal</button>
    </form>
  );
};

enteredText 를 useState 상태관리를 통해서 값이 전달될때 화면에 보여준다

5. useState 피해라

5.1 양식데이터 처리

function LoginForm() {
  const [email, setEmail] = useState('');

  return <input 
    type="email" 
    onChange={(event) => setEmail(event.target.value)}
    value={email} />
}

input일반적으로 React의 양식은 요소를 상태 변수에 연결하고 키를 누를 때마다 상태를 업데이트하여 관리됩니다 . 이 접근 방식은 효과가 있지만 특히 대규모 형식이나 복잡한 애플리케이션에서는 불필요한 다시 렌더링 및 성능 문제가 발생할 수 있습니다.

function LoginForm() {
  const emailRef = useRef(null);
  const passwordRef = useRef(null);

  function handleSubmit(event) {
    event.preventDefault();
    const email = emailRef.current.value;
    const password = passwordRef.current.value;
  };

  return (
    <form onSubmit={handleSubmit}>
      <input ref={emailRef} type="email" placeholder="Email" />
      <input ref={passwordRef} type="password" placeholder="Password" />
      <button type="submit">Login</button>
    </form>
  );
}

입력 필드를 상태 변수에 바인딩하는 대신 useRef후크와 함께 제어되지 않는 구성 요소를 사용하는 것이 좋습니다. 이 접근 방식에는 양식 제출 시 DOM에서 직접 입력 값을 읽어 다시 렌더링 횟수를 줄이고 성능을 향상시키는 작업이 포함됩니다.

5.2 양식 제출을 위해 브라우저 기능을 활용

function LoginForm() {
  function handleSubmit(event) {
    event.preventDefault();
    const formData = new FormData(event.target);
    const email = formData.get('email');
    const password = formData.get('password');
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="email" type="email" placeholder="Email" />
      <input name="password" type="password" placeholder="Password" />
      <button type="submit">Login</button>
    </form>
  );
}

브라우저의 기본 양식 제출 기능을 활용하면 양식 처리를 더욱 간소화할 수 있습니다. 제출 이벤트에서 양식 데이터에 액세스하면 양식 입력 관리 시 브라우저의 효율성에 의존하여 필요성 useState을 완전히 제거할 수 있습니다.

5.3 URL 상태저장

function ProductList () {
  const [searchParams, setSearchParams] = useSearchParams();
  const listData = [...FRUIT].sort((a, b) =>
    searchParams.get('sort') === 'ascending' ? a.localeCompare(b) : b.localeCompare(a)
  );

  function handleSort(ascending = true) {
    setSearchParams({ sort: ascending ? 'ascending' : 'descending' });
  }

	// render UI
}

목록의 필터 또는 정렬 옵션과 같은 특정 유형의 상태의 경우 상태를 URL에 저장하는 것이 유리할 수 있습니다. 이 접근 방식은 페이지를 다시 로드할 때 상태를 보존할 뿐만 아니라 특정 애플리케이션 상태를 공유하고 북마크할 수도 있습니다.

5.4 로컬 저장소로 상태유지

const isDarkModeStored = localStorage.getItem('isDarkMode');

export default function DarkMode() {
  const [isDarkMode, setIsDarkMode] = useState(isDarkModeStored === 'true');

  function handleToggleMode() {
    setIsDarkMode((wasDarkMode) => !wasDarkMode);
    localStorage.setItem('isDarkMode', !isDarkMode);
  }

  // render UI
}

사용자 기본 설정과 같은 장기적인 상태 지속성을 위해서는 로컬 스토리지가 유용한 도구가 될 수 있습니다. 이로 인해 의 필요성이 제거되지는 않지만 useState세션 전반에 걸쳐 상태 지속성을 보장하여 이를 보완합니다.

 

728x90