ReactでAPI呼び出しが行われるたびにレンダリングされるローダーコンポーネントを追加したいと思います。 reduxの代わりにreact context + hooksを使用したい。
反応フックのルールが言うように、反応コンポーネントの外で反応フックを使用すべきではありません。しかし、私はSHOW_LOADER
およびHIDE_LOADER
以下のAxiosインターセプター内。
これを達成する方法はありますか?
import axios from "axios";
axios.interceptors.request.use(
config => {
dispatch({
type: "SHOW_LOADER"
})
return config;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
axios.interceptors.response.use(
response => {
dispatch({
type: "HIDE_LOADER"
})
return response;
},
error => {
dispatch({
type: "HIDE_LOADER"
})
return Promise.reject(error);
}
);
function GlobalLoader(){
const [state,dispatch] = useContext(LoaderContext);
return(
<div>
{
state.loadStatus &&
<Loader
type = "Puff"
color = "#00BFFF"
height = {100}
width = {100}
timeout = {3000} />
}
</div>
);
}
export default GlobalLoader;
さらに情報が必要な場合はお知らせください:)
axios.create(config)
を使用してaxiosインスタンスを作成します。 useEffect()
内でこのインスタンスを使用して、状態に影響を与える可能性のあるインターセプターを追加します(リデューサーはここではやりすぎです)。ここでインスタンスをどこでも使用すると、インターセプターによって状態が変化します。
注:複数のリクエストが開始/終了する可能性があるため、カウンタを使用する必要があります。要求に応じて増加し、応答に応じて減少します。カウンターが0
でない場合、アプリケーションはロードされています。
const { useState, useCallback,useMemo, useRef, useEffect } = React;
const ax = axios.create(); // export this and use it in all your components
const useAxiosLoader = () => {
const [counter, setCounter] = useState(0);
const inc = useCallback(() => setCounter(counter => counter + 1), [setCounter]); // add to counter
const dec = useCallback(() => setCounter(counter => counter - 1), [setCounter]); // remove from counter
const interceptors = useMemo(() => ({
request: config => (inc(), config),
response: response => (dec(), response),
error: error => (dec(), Promise.reject(error)),
}), [inc, dec]); // create the interceptors
useEffect(() => {
// add request interceptors
ax.interceptors.request.use(interceptors.request, interceptors.error);
// add response interceptors
ax.interceptors.response.use(interceptors.response, interceptors.error);
return () => {
// remove all intercepts when done
ax.interceptors.request.eject(interceptors.request);
ax.interceptors.request.eject(interceptors.error);
ax.interceptors.response.eject(interceptors.response);
ax.interceptors.response.eject(interceptors.error);
};
}, [interceptors]);
return [counter > 0];
};
const GlobalLoader = () => {
const [loading] = useAxiosLoader();
return(
<div>
{
loading ? 'loading' : 'not loading'
}
</div>
);
}
// make a request by using the axios instance
setTimeout(() => {
ax.get('https://swapi.co/api/people/1');
ax.get('https://swapi.co/api/people/2');
ax.get('https://swapi.co/api/people/3');
}, 1000);
ReactDOM.render(
<GlobalLoader />,
root
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>