본문 바로가기
Programming/React.js

10. immer사용하여 불변성 유지하기

by _S0_H2_ 2022. 8. 31.
728x90
반응형

불변성을 유지하면서 상태를 업데이트하는 것은 렌더링 관점에서 중요하다. 하지만 객체의 구조가 깊어지면 불변성을 유지하면서 이를 업데이트 하는 것이 어렵기 때문에 immer 라이브러리를 통해 짧게 구현할 수 있다. (필수는 아니다)

 

1 ) immer 설치

yarn add immer

2 ) file 생성

import {useRef, useCallback, useState} from 'react';
import './App.css';

function App() {
  const nextId = useRef(1);
  const [form, setForm] = useState({name: '', username: ''})
  const [data, setData] = useState({
    array: [],
    uselessValue: null
  });

  const onChange = useCallback(
    e => {
      const {name, value} = e.target;
      setForm({
        ...form,
        [name] : [value]
      });
    },
    [form]
  );

  const onSubmit = useCallback(e => {
    e.preventDefault();
    const info = {
      id : nextId.current,
      name : form.name,
      username : form.username
    };

    setData({
      ...data,
      array: data.array.concat(info)
    });

    setForm({
      name:'',
      username:''
    });
    nextId.current += 1;
  },
  [data, form.name, form.username])

  const onRemove = useCallback(
    id => {
      setData({
        ...data,
        array: data.array.filter(info => info.id !== id)
      });
    },
    [data]
  );
  
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          name = "username"
          placeholder="아이디"
          value={form.username}
          onChange={onChange}
          />
          <input
            name="name"
            placeholder="이름"
            value={form.name}
            onChange={onChange}
            />
            <button type="submit"> 등록 </button>
      </form>
      <div>
        <ul>
          {data.array.map(info => (
            <li key={info.id} onClick={() => onRemove(info.id)}>
              {info.username} ({info.name})
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

export default App;

아이디와 이름을 등록하면 아래에 목록이 생성된다.

immer를 사용하면 불변성을 유지하는 작업을 간단히 처리할 수 있다.

 

3 ) immer를 적용한 코드

setForm 부분에서 data 저장방식을 변경한다.

import {useRef, useCallback, useState} from 'react';
import produce from 'immer';

function App() {
  const nextId = useRef(1);
  const [form, setForm] = useState({name: '', username: ''})
  const [data, setData] = useState({
    array: [],
    uselessValue: null
  });

  const onChange = useCallback(
    e => {
      const {name, value} = e.target;
      setForm(
        produce(form, draft => {
          draft[name] = value;
        })
      );
    },
    [form]
  );

  const onSubmit = useCallback(e => {
    e.preventDefault();
    const info = {
      id : nextId.current,
      name : form.name,
      username : form.username
    };

    setData(
      produce(data, draft => {
        draft.array.push(info);
      }
    ));
  
    setForm({
      name:'',
      username:''
    });
    nextId.current += 1;
  },
  [data, form.name, form.username])

  const onRemove = useCallback(
    id => {
      setData(
        produce(data, draft => {
          draft.array.splice(draft.array.findIndex(info => info.id === id), 1);
        }
        ))},
    [data]
  );
  
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input
          name = "username"
          placeholder="아이디"
          value={form.username}
          onChange={onChange}
          />
          <input
            name="name"
            placeholder="이름"
            value={form.name}
            onChange={onChange}
            />
            <button type="submit"> 등록 </button>
      </form>
      <div>
        <ul>
          {data.array.map(info => (
            <li key={info.id} onClick={() => onRemove(info.id)}>
              {info.username} ({info.name})
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

export default App;

 

728x90
반응형

'Programming > React.js' 카테고리의 다른 글

12. ContextApi  (0) 2022.09.14
11. 라우터로 SPA 개발하기  (0) 2022.09.08
9. 컴포넌트 성능 최적화  (0) 2022.08.24
8. Component styling  (0) 2022.03.08
7. Hooks  (0) 2022.03.06