최적화3 useCallback사용하기

이동규·2024년 1월 6일

React 기초

목록 보기
11/15
const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

메모이제이션된 콜백함수를 반환한다.의존성 배열의 값이 변경될때 에만 변경된 메모이션된 콜백함수를 반환한다.

기존코드

1.data가 [] 배열인 상태로 첫번째 렌더링 , props 전달 및 자식 컴퍼넌트 렌더링
2.setData로인해 data바뀌고 렌더링 ,props 전달 및 자식 컴퍼넌트 렌더링

최적화코드

1.data가 [] 배열인 상태로 첫번째 렌더링 ,props 전달 및 자식 컴퍼넌트 렌더링

2.setData로 인해 data바뀜 ,useCallback으로 props 전달 x, React.memo로 인해 자식 컴퍼넌트 렌더링 x

중요 usecallback을 사용하지 않으면 props를 부모컴퍼넌트에서 렌더링 할 때 props를 2번 전달해 2번 렌더링 된다.

function App() {
  const dataId = useRef(0);
  const [data,setData] = useState<Info[]>([]);

  const getData = async () =>{
    const res:tmp[] =  await fetch(`https://jsonplaceholder.typicode.com/comments`).then((res)=>res.json());
    const initData:Info[]  = res.slice(0,20).map((it)=>{
      return {
          id:it.postId,
          autor:it.email,
          content:it.body,
          emotion:Math.floor(Math.random() * 5)+1,
          createDate: new Date().getTime(),
      }
    });
    setData(initData);
  };

  useEffect(()=>{
    getData();
  },[]);


  const onCreate:oncreate = useCallback((autor:string,content:string,emotion:number)=>{
    const createDate = new Date().getTime();
    const newItem = {
        autor,
        content,
        emotion,
        createDate,
        id:dataId.current,
    };
    dataId.current+=1;
    setData((prev)=>[newItem,...prev]);
  },[]); 

  
  return (
    <div className="App">
      <DiaryEditor onCreate={onCreate}/>
      <div>전체 일기 :{data.length}</div>
      <div>기분 좋은 일기 개수:{goodCount}</div>
      <div>기분이 나쁜 일기 개수:{badCount}</div>
      <div>기분이 좋은 일기 비율:{goodRatio}%</div>

    
      <DiaryList onDelete={onDelete} onEdit={onEdit} setList={data} />
    </div>
  );
}

export default App;
const DiaryEditor = ({onCreate}:{onCreate:oncreate}) => {
    useEffect(()=>console.log("Diaryeditor렌더"));

    const autorInput = useRef<HTMLInputElement>(null);
    const textInput= useRef<HTMLTextAreaElement>(null);
    const [state, setState] =  useState(
        {
            autor:"",
            content:"",
            emotion:1
        }
    );

    const handleChange = (e:ChangeEvent<HTMLInputElement | HTMLTextAreaElement| HTMLSelectElement>)=>{
        setState({...state,[e.target.name]:e.target.value});
    }
    

    
    return(
        <div className="DiaryEditor">
            <h2>오늘의 일기</h2>
            <input
                ref={autorInput}
                name="autor"
                placeholder="작성자"
                
                value={state.autor} 
                onChange={(e)=>{
                   let tmp = {...state};
                   tmp.autor = e.target.value;
                   setState(tmp);
                }}

            />
            <div>
                <textarea
                    ref={textInput}
                    name="content"
                    placeholder="내용"
                    value={state.content}
                    onChange={handleChange}/>
            </div>

            <div>
                <span style={{fontSize:12}}>오늘의 감정 점수 :</span>
                <select
                   name="emotion" value={state.emotion} onChange={handleChange}>
                    <option value={1}>1</option>
                    <option value={2}>2</option>
                    <option value={3}>3</option>
                    <option value={4}>4</option>
                    <option value={5}>5</option>
                </select>
            </div>
            <button onClick={()=>handleSubmit()}>일기 저장하기</button>
        </div>
    ) 
};
export default React.memo(DiaryEditor);

0개의 댓글