-
Notifications
You must be signed in to change notification settings - Fork 0
[기술 공유] useAxios test code
Coa edited this page Mar 1, 2022
·
1 revision
useAxios.test.ts
import { renderHook } from '@testing-library/react-hooks';
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import useAxios from './useAxios';
const stubbedStocks = [
{ symbol: 'AAPL', price: 1 },
{ symbol: 'GOOG', price: 2 },
];
const stubbedFetchUrl = 'api/stocksUrl-mocked';
const server = setupServer();
beforeEach(() => server.resetHandlers());
beforeAll(() => server.listen());
afterAll(() => server.close());
describe('useAxios는', () => {
it('페치 후에 데이터를 반환해야 한다.', async () => {
server.use(
rest.get(stubbedFetchUrl, (req, res, ctx) => {
return res(ctx.json(stubbedStocks));
})
);
const { result, waitForNextUpdate } = renderHook(() =>
useAxios(stubbedFetchUrl)
);
await waitForNextUpdate();
expect(result.current).toStrictEqual({
loading: false,
data: stubbedStocks,
error: null,
});
});
it('에러를 캐치해야 한다.', async () => {
server.use(
rest.get(stubbedFetchUrl, (req, res, ctx) => {
return res(
ctx.status(403),
ctx.json({ errorMessage: 'Stocks not found' })
);
})
);
const { result, waitForNextUpdate } = renderHook(() =>
useAxios(stubbedFetchUrl)
);
await waitForNextUpdate();
console.log(result.current);
expect(result.current).toStrictEqual({
loading: false,
data: null,
error: 'Stocks not found',
});
});
});
useAxios.tsx
import axios from 'axios';
import { useState, useEffect } from 'react';
const axiosConfig = {
headers: {
'Content-Type': 'application/json',
accept: 'text/html; charset=utf-8',
},
};
interface ReturnType<S> {
data: S | null;
loading: boolean;
error: unknown;
}
function useAxios<S>(url: string): ReturnType<S> {
const [data, setData] = useState<S | null>(null);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<unknown>(null);
const fetchData = async () => {
try {
const res = await axios.get(url, axiosConfig);
if (res.status === 200) {
setLoading(false);
setData(res.data);
} else new Error();
} catch (e) {
// check if the error was thrown from axios
if (axios.isAxiosError(e)) {
// // do something
// // or just re-throw the error
// // ex) throw e;
setLoading(false);
setError(e.response ? e.response.data.errorMessage : e.message);
} else {
// // do something else
// // or creating a new error
// // ex) throw new Error('different error than axios');
setLoading(false);
setError('different error');
}
}
};
useEffect(() => {
fetchData();
return () => setLoading(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return { data, loading, error };
}
export default useAxios;
- useEffect에서 fetchData를 실행시킨다.
- fetchData를 처음 실행시키고 난 다음에 다시 useEffect를 만나게 되면? useEffect의 deps = [fetchData]인 상태이기 때문에 다시한번 useEffect된다. 무한 페칭이 걸린다.
- 따라서 fetchData를 useCallback으로 감싸고 deps = [url]을 주면 fetchData를 호출한 다음 fetchData가 변경되었는지를 판단했을 때 url의 변화가 없으므로 memoization된 fetchData를 기준으로 비교하여 변경되지 않았다고 판단한다.
- fetchData가 변경되지 않으면 useEffect도 실행되지 않는다.
😎@Daewon Seo 🥳@papa 🧐@Coa 🤪@HuiSeung LEE
Test 관련 이슈
Next.js 관련 이슈
Git 관련 이슈
기타 이슈
기술공유
- [strapi] authenticated request 구현하기
- aria label는 왜 쓰는 것인가?
- font icon을 집어 넣을 때 i 태그로 넣을까? pseudo elements(before, after)로 넣을까?
- Nextjs에서 a 태그를 Link 태그로 감싸야 한다.
- Nextjs에서 img 대신 Image 컴포넌트 사용하기, next.config.js는 무엇인가?
- React.FC
- React.js rest Props와 Object destructuring
- Reactjs 컴포넌트 선언 방식을 화살표 함수로 할지 함수 선언문으로 할지
- Test 참고
- useAxios test code
- 뷰포트 메타태그, Next.js에서 Head 태그란?
- 스타일이 중복되서 들어갈 때 그룹 셀렉터 대신 mix를 쓰거나, 아니면 만든 mix의 modifier를 만들어주거나, 각각에 주거나.
- 타입스크립트 클래스에서의 protected, private 필드와 # 필드의 차이
- Global state VS local state 리덕스의 배경이해, 글로벌 변수와 다를 바 없다면 지양되어야 하지 않나?
- Fontawesome Icon React 적용방법
- classnames/bind 함수와 classnames 함수의 차이
- Jest와 Testing Library