[React] useRef 예제

겨레·2024년 11월 28일
post-thumbnail

useRef 간단 예제

import React, { useRef } from 'react';  // useRef 임포트 필수!

const UseRef_example = () => {
  // useRef(0) => counterRef 변수에 초기값 0인 ref 객체 생성
  const counterRef = useRef(0);  

  // counterUp 함수 => 버튼 클릭 시 실행됨
  const counterUp = () => {
    // counterRef.current => counterRef 객체의 현재 값을 추적
    // current는 ref 객체의 속성으로, 값에 접근하거나 변경할 때 사용함
    counterRef.current += 1; // counterRef의 값을 1 증가시킴
    console.log('Counter:', counterRef.current); // 변경된 값 콘솔창 출력
  };
  return (
    <div>
      <p>ref 값 : {counterRef.current}</p>
      <button onClick={counterUp}>counterUp 버튼</button>
    </div>
  );
};

export default UseRef_example;

counterUp 버튼을 눌러 보자!

counterUp 버튼을 누르면 콘솔창에는 1씩 증가하는 것을 볼 수 있다.
하지만 화면에 보이는 ref 값은 바뀌지 않고 여전히 0인 것을 확인할 수 있다.


[React] 기능 구현_②항목 추가 기능 구현에서 작성했던 코드

① 먼저 할 일을 입력하고 + 버튼을 누르면, todos 배열에 새로운 할 일을 추가하는 onInsert 함수를 만들어주자!

이때, useState 말고 useRef를 사용할 거임!
왜❓🤔
👉 드래그로 확인
지금 todos 배열을 보면 각 할 일마다 1, 2, 3이라는 고유 id 값이 있는데 이 id 값은 화면에 렌더링될 필요가 없기 때문!

useRef로 nextId라는 참조 객체 생성하고 id 3번 이후에 추가되어야 하니까 id 초기값은 4로 설정해준다.

② + 버튼을 누르면 실행 될 onInsert 함수를 만들 차례!

이때 useCallback으로 감싸줄 거임!
왜❓🤔
👉 코드 하단에 retrun ( )을 보면 < TodoInsert onInsert= {onInsert} /> 요렇게 props로 전달되는데 이때, 불필요함 함수 재생성을 방지해 불필요한 렌더링을 막기 위해 useCallback으로 감싸주는 것!


  • UseRef_todoApp_App.jsx
import React, { useState, useRef, useCallback } from 'react';
import TodoTemplate from '../components/TodoTemplate';
import TodoInsert from '../components/TodoInsert';
import TodoList from '../components/TodoList';

const UseRef_todoApp_App = () => {
  /* todos 배열 안에 들어 있는 객체 
     => 각 항목의 고유 id, 내용, 완료 여부를 알려 주는 값이 있음.
  */
  const [todos, setTodos] = useState([
    {
      id: 1,
      text: '리액트 기초 알아보기',
      checked: true,
    },
    {
      id: 2,
      text: '컴포넌트 스타일링해 보기',
      checked: true,
    },
    {
      id: 3,
      text: '일정 관리 앱 만들어 보기',
      checked: false,
    },
  ]);

  // nextId라는 useRef 객체를 생성
  // 초기값은 4
  const nextId = useRef(4);

  const onInsert = useCallback(
    // text 값을 받아 todo 객체를 생성해 todos 배열에 추가
    (text) => {
      const todo = {
        id: nextId.current, // nextId.current 값을 사용해 고유 ID 생성
        text, // 입력받은 text 값
        checked: false, // 기본 checked 값은 false
      };
      
      // 새로운 배열을 setTodos 함수에 전달해 todos 상태를 업데이트
      // concat => 원본 배열을 변경하지 않고, 새로운 배열을 반환
      setTodos(todos.concat(todo)); // 새로운 todo 배열을 todos 배열에 추가
      nextId.current += 1;  // useRef로 생성된 객체 nextId의 current 속성 값에 1씩 더함
    },
    [todos], // 의존성 배열 => todos 배열이 변경될 때만 onInsert 함수가 새로 생성됨
  );

  return (
    <TodoTemplate>
      {/* <TodoInsert /> */}
      <TodoInsert onInsert={onInsert} />
      {/* <TodoList /> */}
      {/* todos 배열을 TodoList로 전달 */}
      <TodoList todos={todos} />
    </TodoTemplate>
  );
};

export default UseRef_todoApp_App;

③ Todo 앱의 입력 폼에 작성하는 컴포넌트도 작성해보자!

사용자가 입력한 할 일을 받아서 부모 컴포넌트로 전달하는 역할을 한다.
이 컴포넌트는 useState 훅을 사용해 입력값을 관리하고,
마찬가지로 useCallback을 사용해 함수들이 불필요하게 재생성되지 않도록 최적화시켰다.

  • UseRef_todoApp_TodoInsert.jsx
import React, { useState, useCallback } from 'react';
import { MdAdd } from 'react-icons/md'; // 아이콘 사용
import '../TodoInsert.scss';

const UseRef_todoApp_TodoInsert = ({ onInsert }) => {
  // value => 현재 상태 값 (사용자가 입력한 값).
  // setValue => value를 업데이트하는 함수.
  const [value, setValue] = useState(''); // 초기값은 빈문열

  // onChange 함수 => input 필드에서 값이 변경될 때마다 호출됨
  const onChange = useCallback((e) => {
    // e.target.value => input에 입력된 값을 전달 받고
    // 그 값을 value 상태로 업데이트함.
    setValue(e.target.value);
  }, []);

  // onSubmit 함수 => 폼을 제출했을 때 호출됨
  const onSubmit = useCallback(
    (e) => {
      // 자식 컴포넌트인 UseRef_todoApp_TodoInsert에서 이 onInsert(value)를 호출하면,
      // 입력된 텍스트가 부모 컴포넌트로 전달됨.
      onInsert(value);
      setValue(''); // 새 할일 제출 후, value 값 초기화

      // submit 이벤트는 브라우저에서 새로고침을 발생시킴.
      // 이를 방지하기 위해 preventDefault 함수를 호출함.
      e.preventDefault();
    },
    [onInsert, value],
  );

  return (
    <form className="TodoInsert" onSubmit={onSubmit}>
      {/* placeholder => 입력 필드(input, textarea 등)의 힌트 텍스트 */}
      <input
        placeholder="할 일을 입력하세요"
        value={value}
        onChange={onChange}
      />
      <button type="submit">
        <MdAdd />
      </button>
    </form>
  );
};

export default UseRef_todoApp_TodoInsert;

새로운 할 일을 입력하고 + 제출 버튼을 누르기 전을 보면
기존 todos 3개가 나와 있음.

새로운 할 일을 추가하고, + 제출 버튼까지 눌러보자!

확인하면 + 제출 버튼을 누름과 동시에 새 할일 제출 후, value 값 초기화되어 placeholder="할 일을 입력하세요"가 나와있고 onInsert가 호출되면서 TodoListItem이 새롭게 추가된 것을 볼 수 있다.

profile
호떡 신문지에서 개발자로 환생

0개의 댓글