리덕스에서 async 비동기 코드를 처리하는 2가지 방법

thumbzzero·2023년 9월 29일
0

1. 컴포넌트 내에서 실행

useEffect() 사용

// 컴포넌트 내부
const data = useSelector((state) => state.data);

useEffect(() => {
  fecth(API_URL, {
    method: 'POST',
    body: JSON.stringify(data),
  });
}, [data]);

useEffect() 문제 : 앱이 시작될 때 실행됨
=> 코드 수정

// 컴포넌트 외부
let isInitial = true;  // 컴포넌트가 리렌더링돼도 다시 초기화되지 않음 (파일이 처음으로 parse될 때 초기화)


// 컴포넌트 내부
const data = useSelector((state) => state.data);

useEffect(() => {
  const sendData = async () => {
  	const response = await fecth(API_URL, {
      method: 'POST',
      body: JSON.stringify(data),
    });
    
    if (!response.ok) {
   		// 실패 처리
    }
    
    // 성공 처리
  };
  
  if (isInitial) {
    isInitial = false;  // 앱이 처음 시작될 때만 sendData() 차단
    return;
  };
  
  sendData();
  
}, [data]);

2.작업 생성자 생성

작업 생성자(action creators)를 생성하여 비동기 코드 실행

thunk
: 다른 작업이 완료될 때까지 작업을 지연시키는 단순한 함수

작업 객체를 즉시 반환하지 않는 작업 크리에이터를 작성하기 위해 thunk로 작업 크리에이터를 작성

=> 작업을 반환하는 다른 함수를 반환

원래 만들려고 했던 실제 작업 객체를 dispatch하기 전에 다른 코드 실행

// 별도의 함수
// 함수를 반환하는 action creator
export const fetchData = () => {
  return async (dispatch) => {
    const sendRequest = async () => {
      const response = await fetch(API_URL);
      
      if (!response.ok) {
        throw new Error('Could not fetch data');
      }
      
      const data = await response.json();
      
      return data;
    };
    
    try {
      const data = await sendRequest();
      dispatch(ACTIONS.ACTION_CREATOR(PAYLOAD))
    } catch (error) {};
  };
};

export const sendData = (data) => {
  // 아직 리듀서에 도달하지 않았으므로 비동기 코드 수행 가능
  return async (dispatch) => {
    const sendRequest = async () => {  
      const response = await fecth(API_URL, {
        method: 'POST',
        // body: JSON.stringify(data),
        body: JSON.stringify({/* 새 객체 생성 */}),
      });
      
      if (!response.ok) {
   		// 실패 처리
      }
      
      // 성공 처리
    };
    
    try {
      await sendRequest();
      dispatch(ACTIONS.ACTION_CREATOR(PAYLOAD)));
    } catch (error) {}
  };
};
// 컴포넌트 내부
const dispatch = useDispatch();
const data = useSelector((state) => state.data);

useEffect(() => {
  dispatch(fetchData());
}, [dispatch]);

useEffect(() => {
  if (isInitial) {
    isInitial = false;
    return;
  }
  if (data.changed) {
  	dispatch(sendData(data));  // 다른 함수를 반환하는 함수를 전달
  }
}, [data, dispatch]);

0개의 댓글