Привет, я не уверен, что лучший способ издеваться над реагирующим крючком. Я хочу проверить страницу. js, которая имеет входы и отправить данные входов на сервер через запрос POST. Когда запрос выполнен успешно, появляется другая форма.
Я хочу проверить успешное выполнение.
Я использую пользовательский хук, вызывающий api, и его имя - useApi. Итак, я высмеял useApi, чтобы вернуть статус успеха. У меня есть 2 хука useAPI, и хуки вызываются при каждом рендеринге.
, поскольку setState of useState вызывает рендеринг, когда он вызывается, каждый useApi вызывается снова. поэтому должно быть много useApi.mockReturnValueOnce ().
было бы так много useApi.mockReturnValueOnce (), если есть больше useApi. это было бы очень неприятно, поэтому я выясняю, есть ли лучший метод.
У вас есть идеи?
// Page.js
const Page = () => {
const [api, requestApi] = useApi(
'/v1/users/me/marketing_agreement',
{
method: 'post',
manual: true,
}
)
const [verifyApi, requestVerifyApi] = useApi(
'/v1/users/me/verify_password',
{
method: 'post',
manual: true,
}
)
...
return (
<div>
{api.status === 'success' ? <p>success</p> : null}
<form
onSubmit={e => {
requestApi();
}}
>
<input name="a" />
...
</form>
</div>
)
}
// Page.test. js
test('test', async () => {
// api
useApi.mockReturnValueOnce([{ status: 'init' }, requestApi]);
// verifyApi
useApi.mockReturnValueOnce([{ status: 'init' }, requestApi]);
// api
useApi.mockReturnValueOnce([{ status: 'success' }, requestApi]);
// verifyApi
useApi.mockReturnValueOnce([{ status: 'init' }, requestApi]);
// api
useApi.mockReturnValueOnce([{ status: 'success' }, requestApi]);
// verifyApi
useApi.mockReturnValueOnce([{ status: 'init' }, requestApi]);
...some tests changing state of Page (and the page call useApi again because of rerendering)
})
// useApi. js
import { useReducer, useEffect } from 'react';
import request from 'libs/request';
const initialState = { status: 'init', data: null, error: null };
function reducer(_, action) {
switch (action.type) {
case 'request':
return { status: 'loading' };
case 'success':
return { status: 'success', data: action.data };
case 'failure':
return { status: 'failure', error: action.error };
default:
throw new Error();
}
}
export default (url, options = { method: 'get', manual: false }) => {
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
let cancelled = false;
if (!options.manual) {
dispatch({ type: 'request' });
const { manual, ...others } = options;
request({ url, ...others })
.then(result => {
if (!cancelled) {
dispatch({ type: 'success', data: result.data });
}
})
.catch(e => {
if (!cancelled) {
dispatch({ type: 'success', error: e });
}
});
}
return () => {
cancelled = true;
};
}, [options, url]);
if (options.manual) {
const requestApi = async props => {
dispatch({ type: 'request' });
try {
const { manual, ...others } = options;
const result = await request({
url,
method: options.method,
...others,
...props,
});
dispatch({ type: 'success', data: result.data });
return result;
} catch (e) {
dispatch({ type: 'failure', error: e });
return null;
}
};
return [state, requestApi];
}
return [state];
};