본문으로 바로가기

TIL 2022-05-28 Goodbye, useEffect

category TIL 2022. 5. 28. 21:39

https://www.youtube.com/watch?v=HPoC-k7Rxwo 

 

 

요거 봣음

 

useEffect(()=>{


},[]);

 

Imperative하게는 어떤 일이 일어나면 effect를 실행한다지만

 

declarative하게는

 

-> 어떤 일이 일어나면

-> state를 변화시키고

-> 어떤 state를 변화시켰는지에 따라서

-> 이 effect는 일어난다

-> 근데 또 어떤 조건이 참일때만

-> 그리고 이거 일어나면 React가 (concurrent rendering)때문에 재실행할수도 있음

 

이라는 복잡한 로직을 갖게 된다.

 

 

React 18에서는 strict mode일때 useEffect를 두번 실행한다.

 

18에서는 effect를 발생시키는 component를 mount하고, 이를 가상으로 cleanup해 unmount하고 이를 다시 mount하는 과정을 거친다. 이 과정에서 두번 실행됨.

 

 

useEffect는 언제 써야하는가?

 

React 공식 문서에 있는 subscription이나, network나, DOM 등의 외부 시스템이랑 리액트가 동기화해야할때!

 

그냥 리액트 내부 데이터 흐름을 useEffect로 해결하려고 하니까 이런 문제들이 생기는거임

 

리액트 beta 문서에 따르면 side-effect는 event-handler에서 처리하는게 제일 좋음! useEefect에서 처리하는건 최대한 지양하는게 좋다. 라고 적혀져있다.

 

Effect들을 렌더링해야하는 컴포넌트에 넣으면 리액트 18에서 effect가 두번 실행되는 문제같은게 생기는거임. 컴포넌트 렌더링할때에 위치하기 때문.

 

Event Handler에 위치하면 얼마나 렌더링을 하던 문제 X! 왜냐하면 리액트에서는 State to State Transition은 딱 한번 일어나는게 보장되어있지만 Rendering은 그렇지 않다. 그러니 effect는 rendering 바깥에서 일어나야함.

 

React에서는 UI는 state의 함수라는 모토가 있어 Redux 등에서는

state, event => nextState

state와 이것에 대한 event를 통해서 새로운 state를 생성하는 공식을 도입함. 근데 여기는 Effect가 들어갈 자리가 없음!

 

그러면 effect를 어디 넣어야하는가? State Transition 사이에 넣어야함!

 

왜냐하면 effect를 발생한다는 것은 어떤 것이 이 effect를 발생시켰다는 것이고, 그래서 대체로 event handler에 들어가는 것을 권장했던 거임. 동일한 의미로 state -> nextState로 변하는 과정에서 effect를 추가해주는 거임

state, event => nextState, effect

 

	
import { useState, useCallback } from 'react';
 
function useSpicyReducer(reducer, initialState, executeEffect) {
  const [state, setState] = useState(initialState);
 
  const spicyDispatch = useCallback(
    (event) => {
      // Calculate next state
      const nextState = reducer(state, event);
      
      // Execute effect based on transition
      executeEffect(state, event, nextState);
      
      // Commit next state
      setState(nextState);
    },
    [reducer, state, executeEffect]
  );
 
  return [state, spicyDispatch];
}

위 코드의 중요한점은 state transition, effect가 전부 dispatch 내에서 다 일어나는거임. 그리고 이 Dispatch는 event handler 내에서 일어남

 

state transition 내에서 effect를 다루는 좋은 방법은 External Store를 사용하는 거임.

 

useSyncExternalStore

이것은 컴포넌트와 컴포넌트 외부에 있는 store가 통신하고, sync를 맞출수 있게 해줌. 그리고 이 store에서 state를 관리하고 effect를 다 처리해줄수 있음. 이런 것들을 사용해서 State management의 일환으로 effect를 처리해주는것이 바람직함.

 

결론

 

Effect는 상태 관리의 일부이지 side-effect로 취급하면 안된다!

 

useEffect는 동기화를 위해 사용되어야지 effect를 처리하기 위함이 아님! State transition이 effect를 발생시키므로 거기서 effect를 다뤄야함!

'TIL' 카테고리의 다른 글

TIL 2022-06-18 HTTP Overview - Basic aspects  (0) 2022.06.18
TIL 2022-06-17 HTTP Overview - Component  (0) 2022.06.17
TIL 2022-05-21 Abstract Factory  (0) 2022.05.21
TIL 2022-05-17 Web Page Transition  (0) 2022.05.17
TIL 2022-05-14 State of CSS 보기  (0) 2022.05.14