React : Immer & 함수형 업데이트

import React from ‘react’

import {useState , useRef, useCallback} from ‘react’

 

import produce from ‘immer’

function App()
{
 
     const nextId = useRef(1);
     const inputname = useRef()
     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]
      })
    
      /* 또는 , immer 를 이용한 상태 업데이트 */
      setForm(
        produce(form , draft => {        
          draft[name] = value
        })
      )   

  }, [form]) 

useCallback 으로 함수를 memoizaion 할 경우 반드시 의존성배열에  상태가변경될경우 업데이트 되어야할 상태변수를 나열해준다.
그렇치 않으면 onChange 함수가 memoizaion 될대 저장한
form 값({ name:” , username:”})을  계속해서 사용함

단, useCallback 에서 변경한 상태는 실제 상태에서 적용됨

  const onChange = useCallback( (e) => {
   
      const {name , value} = e.target;

      setForm ( e => {
        return {
          …e,
          [name] : [value]
        }
      })

       /* 또는 , immer 를 이용한 함수형 업데이트 */
 
       //  produce(사본객체 => { 사본객체 활용 }

      setForm( produce(draft => {
          draft[name] = value;
        })
      )
  }, [ ])

  [ 함수형 업데이트 ]
– Immer 에서 함수형 업데이트 사용시 원본파라미터      생략 해야한다. 
함수형 업데이트의 경우 useCallback 를 이용하여       memoizaion 하더라도 항상 상태값의 최신값을
   가져 올 수가 있으므로
  의존성 배열은 [ ] 제거하고

   최초 1회 렌더링만 한다.
const onSubmit = useCallback( (e) => {
    e.preventDefault()

    const info = {
        id : nextId.current ,
        name : form.name,
        username : form.username
    }
 
     setData({
          array : data.array.concat(info)
     });
       setData(produce(data , draft => {
              draft.array.push(info);
        }))

       //  produe(원본 , 사본 => {
               사본활용 
          }

    setForm({name : ” , username:”})

    nextId.current = nextId.current + 1;

    inputname.current.focus();
  }, [form , data] );
  const removeItem = useCallback((id) => {
 
    setData(
      {    
           array : data.array.filter(e =>e.id !== id)
      }
    )
 
  },[data]);
 
  return(
    <div>
      <form onSubmit={onSubmit}>
        <input name=”username”
                   placeholder=”아이디”
                   ref={inputname}
                   value={form.username}
                   onChange={onChange}/>
        <input  name=”name”
                    placeholder=”이름”
                    value={form.name}
                   onChange={onChange} />
        <button type=”submit”>등록하기</button>
       </form>
      <div>
        <ul>
        { data.array.length }
        {
          data.array.map( e => {
            return <li key={e.id} onClick={()=>removeItem(e.id)}>
                              {e.id} / {e.name} {e.username}
                      </li>
              })
          }
          </ul>
        </div>
      </div>
   )
}
export default App;
 
 

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다