React/기초

[React] immer를 사용해서 불변성 유지하기

Judith Hopps 2023. 3. 16. 08:17
반응형

immer

구조가 복잡한 객체도 매우 쉽고 짧은 코드를 사용하여

불변성을 유지하면서 업데이트해 줄 수 있다.

 

immer 사용하지 않고 불변성 유지하기

import React,{useRef,useCallback,useState} from 'react';

const 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='아이디' 
              vlaue={form.userName} onChange={onChange} />
        <input name ="name" placeholder='이름' 
        vlaue={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  설치

npm install immer

 

 

app.js 수정

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


const 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(draft => {
          draft[name] = value;
        })
      )
    }, []
  )

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

      setData(
        produce(draft => {
          draft.array.push(info);
        })
      )

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

  const onRemove = useCallback(
    id => {
      setData(
        produce(draft => {
          draft.array.splice(draft.array.findIndex(info => info.id === id), 1)
        })
      )
    }, [data]
  )
  return (
    <div>
      <form onSubmit={onSubmit}>
        <input name ="userName" placeholder='아이디' 
              vlaue={form.userName} onChange={onChange} />
        <input name ="name" placeholder='이름' 
        vlaue={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;
반응형