useSWR을 이용한 Data Fetching

SangBooom·2020년 12월 10일
0

React Native

목록 보기
1/2
post-thumbnail


아래 코드들은 전북대학교 과팅앱 프로젝트의 일부분이다.

// MypageNavigator.js
const MypageNavigator = ({navigation}) => {
 const [myInfo, setMyInfo] = useState([]);
 const [update, setUpdate] = useState();

  const getMyInfo = async () => {
     try {
       const response = await authAPI.getMyInfo({
         headers: {
           'Access-Token': await AsyncStorage.getItem('token'),
         },
       });
       setMyInfo(response.data);
     } catch (error) {
       console.log(error);
     }
   };

   useEffect(() => {
     setUpdate(false);
     onGetMyInfo();
   }, [update]);

 return (
     <MyPageStack.Screen name="유저정보">
       {(props) => <MyPageScreen {...props} navigation={navigation} myInfoData={myInfo} />}
     </MyPageStack.Screen>
     <MyPageStack.Screen name="계정">
       {(props) => <AccountScreen {...props} navigation={navigation} myInfoData={myInfo} update={update} setUpdate={setUpdate} />}
     </MyPageStack.Screen>
     ...
   );
 };
}
// AcccountScreen.js
const onChangeUserInfo = async () => {
    try {
      await authAPI.changeUserInfo(
        userData(),
        {
          headers: {
            'Access-Token': await AsyncStorage.getItem('token'),
          },
        },
      );
      Alert.alert('변경 성공', '회원정보 수정을 완료했습니다.', [
        {
          text: '확인',
          onPress: () => {
            navigation.navigate('유저정보');
          },
        },
      ]);
      setUpdate(!update); //강제 리렌더링
    } catch (error) {
      console.log({error});
    }
  };

문제점
MypageNavigator가 마운트되면 API 호출을 통해 유저 정보를 요청하고 응답을 받는다. 받은 정보는 myInfo에 저장하고 props로 하위 컴포넌트들에게 전달한다.
여기서 만약, 유저가 AccountScreen에서 유저 정보를 수정하고 MyPageScreen으로 이동했다면 MyPageScreen에 보이는 유저의 정보는 수정되지 않았을 것이다. 이 문제를 해결하기 위해 update라는 state를 만들고 setState와 함께 변경이 일어나는 컴포넌트에 props로 전달을 했다. API호출을 통해 정보를 수정하고 setUpdate(!update) 로 강제 리렌더링을 시켰다.
하지만 deps가 깊어지고 유저 정보 API와 의존하는 컴포넌트들이 많다면 일일이 props로 전달하는 건 비효율적이다.

참고
React 컴포넌트가 렌더링을 수행하는 시점은 다음과 같다.

  • Props가 변경되었을 때
  • State가 변경되었을 때
  • forceUpdate() 를 실행하였을 때
  • 부모 컴포넌트가 렌더링되었을 때

해결
SWR이라는 엄청난 라이브러리를 발견했다. SWR 에서 제공하는 Trigger 함수는 reFetch가 필요한 data에 대해 trigger를 이용하여 refetch가 가능하다.
trigger(_key, shouldRevalidate = true)
이와 같은 형태로 trigger에 key를 전달하여 refetch 할 수 있다.
trigger를 사용함으로써 setUpdate(!update)로 일일이 props로 전달해 강제 리렌더링을 시키지 않아도 최신 데이터로 업데이트 할 수 있었다.

참고
SWR은 React Hooks를 사용하여 실시간으로 데이터를 fetch, 캐싱 또는 re-fetch 할 수 있다.
그리고 useState와 useEffect를 사용하지 않고도 데이터 fetch를 쉽게 할 수 있다.
SWR에는 유용한 기능들이 많다. 페이지의 초점을 다시 맞추거나 탭간에 전환하면 swr이 자동으로 데이터의 유효성을 다시 검사하는 옵션도 있고, 초단위 간격으로 데이터를 자동으로 다시 가져오는 기능도 있다..! 정말 센세이션하다! 😮

// MypageNavigator.js
import useSWR from 'swr';
...
const MypageNavigator = ({navigation}) => {
  const MyPageStack = createStackNavigator();

  const fetcher = async (url) => {
    const response = await axios.get(url, {
      headers: {
        'Access-Token': await AsyncStorage.getItem('token'),
      },
    });
    return response.data;
  };

  const {data = [], error} = useSWR(`${Config.baseUrl}/api/users`, fetcher);
  if(error) return console.log(error);

  return (
      <MyPageStack.Screen name="유저정보">
        {(props) => <MyPageScreen {...props} navigation={navigation} myInfoData={data} />}
      </MyPageStack.Screen>
      <MyPageStack.Screen name="계정">
        {(props) => <AccountScreen {...props} navigation={navigation} myInfoData={data} />}
      </MyPageStack.Screen>
      ...
    );
  };
}
// AcccountScreen.js
import {trigger} from 'swr';
...
const onChangeUserInfo = async () => {
    try {
      await authAPI.changeUserInfo(
        userData(),
        {
          headers: {
            'Access-Token': await AsyncStorage.getItem('token'),
          },
        },
      );
      Alert.alert('변경 성공', '회원정보 수정을 완료했습니다.', [
        {
          text: '확인',
          onPress: () => {
            navigation.navigate('유저정보');
          },
        },
      ]);
      trigger(`${Config.baseUrl}/api/users`); //트리거를 통해 실시간으로 최신 데이터를 fetch한다.
    } catch (error) {
      console.log({error});
    }
  };

useSWR 에 대해 찾아보고 공부하면서 정리를 해보았는데 글을 쓰는게 아직 어색해서 정리가 제대로 안된 것 같다. 다음에는 더 이해하기 쉽고 간단명료하게 정리해야겠다.


제가 설명을 잘못한 부분이나 부족한 부분이 있다면 댓글 부탁 드립니다 😎

profile
끊임없이 떨어지는 물방울이 바위를 뚫는다

0개의 댓글