Introduce
This article solves 2 problems
- How to install axios
- How to use react-router-dom in axios interceptor to switch pages without having to reload the whole website
Content
Install axios
- npm:
npm install axios
- yarn:
yarn add axios
Switch pages in interceptor using react-router-dom
Problem
In reactjs or in any single page app
we don’t want to have to re-load the whole page, this makes the browser have to reload all resources (js, css, image, font,..) which reduces the experience. user experience without taking advantage of the power of single page app
. To navigate through pages we usually use the useHistory/useNavigate hook of react-router-dom, but the axios interceptor
is not a react-component so the hook cannot be used. So they must do?
Solution
- Use another react-router-dom which allows to move the page without hooks
- Call interceptor inside react-component to use hook
Logic
Of course, in this article, I will deal with the second direction, the mindset as follows:
- How to set interceptor in component?
- Call the interceptor immediately App.tsx of the project, do not create it only once. So ease!
- If it can be set, how will the places that need to be used axios be used?
- In order for other places (components, functions) to be available, it is necessary to share the instance with the axios interceptor in the App.tsx above.
Coding
B1: Call interceptor right in the first component App.tsx
Here, for example, if the status is 401, it will redirect to /login
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <span class="token keyword">import</span> axios <span class="token keyword">from</span> <span class="token string">'axios'</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">App</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> navigate <span class="token operator">=</span> <span class="token function">useNavigate</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> axiosInstance <span class="token operator">=</span> axios <span class="token punctuation">.</span> <span class="token function">create</span> <span class="token punctuation">(</span> <span class="token punctuation">{</span> baseURL <span class="token operator">:</span> <span class="token string">"http://localhost:3000/api"</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> axiosInstance <span class="token punctuation">.</span> interceptors <span class="token punctuation">.</span> request <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">config</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle before request is sent</span> <span class="token keyword">return</span> config <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">error</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle request error</span> <span class="token keyword">return</span> Promise <span class="token punctuation">.</span> <span class="token function">reject</span> <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> axiosInstance <span class="token punctuation">.</span> interceptors <span class="token punctuation">.</span> response <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">response</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle response data</span> <span class="token keyword">return</span> response <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">error</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle response un-authen error</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> error <span class="token punctuation">.</span> response <span class="token punctuation">.</span> status <span class="token operator">===</span> <span class="token number">401</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">navigate</span> <span class="token punctuation">(</span> <span class="token string">"/login"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> Promise <span class="token punctuation">.</span> <span class="token function">reject</span> <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> RouterProvider router <span class="token operator">=</span> <span class="token punctuation">{</span> routers <span class="token punctuation">}</span> fallbackElement <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"loading..."</span> <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
That’s it, the navigation problem is over
B2: How can I reuse axiosInstance because I only have a custom interceptor for it, if I use another instance, it won’t navigate anymore, should I export it from App.tsx???
To bring back the same instance, there are two ways.
- Method 1: Use singleton pattern
- Method 2: Reuse the library instance itself
Here I will use method 2, and method 1, you guys will find out more by yourself. You just need to replace axiosInstance
with axios
imported directly from the library
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <span class="token keyword">import</span> axios <span class="token keyword">from</span> <span class="token string">'axios'</span> <span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">App</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> navigate <span class="token operator">=</span> <span class="token function">useNavigate</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> axios <span class="token punctuation">.</span> defaults <span class="token punctuation">.</span> baseURL <span class="token operator">=</span> <span class="token string">"http://localhost:3000/api"</span> <span class="token punctuation">;</span> axios <span class="token punctuation">.</span> interceptors <span class="token punctuation">.</span> request <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">config</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle before request is sent</span> <span class="token keyword">return</span> config <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">error</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle request error</span> <span class="token keyword">return</span> Promise <span class="token punctuation">.</span> <span class="token function">reject</span> <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> axios <span class="token punctuation">.</span> interceptors <span class="token punctuation">.</span> response <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">response</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle response data</span> <span class="token keyword">return</span> response <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">error</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle response un-authen error</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> error <span class="token punctuation">.</span> response <span class="token punctuation">.</span> status <span class="token operator">===</span> <span class="token number">401</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">navigate</span> <span class="token punctuation">(</span> <span class="token string">"/login"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> Promise <span class="token punctuation">.</span> <span class="token function">reject</span> <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span> RouterProvider router <span class="token operator">=</span> <span class="token punctuation">{</span> routers <span class="token punctuation">}</span> fallbackElement <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token string">"loading..."</span> <span class="token punctuation">}</span> <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
That’s it, so simple
B3: Fix bug
When you get to this step, you will definitely get an error because you use useNavigate
outside of RouterProvider
. Then just put this pile of code into RouterProvider
. Here I am using react-router-dom 6.8 which may be a bit different from everyone else. But the mindset is to put the interceptor setup inside RouterProvider
to use useNavigate
or useHistory
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <span class="token keyword">import</span> axios <span class="token keyword">from</span> <span class="token string">"axios"</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">OutletContainer</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> navigate <span class="token operator">=</span> <span class="token function">useNavigate</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> axios <span class="token punctuation">.</span> defaults <span class="token punctuation">.</span> baseURL <span class="token operator">=</span> <span class="token string">"http://localhost:3000/api"</span> <span class="token punctuation">;</span> axios <span class="token punctuation">.</span> interceptors <span class="token punctuation">.</span> request <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">config</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle before request is sent</span> <span class="token keyword">return</span> config <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">error</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle request error</span> <span class="token keyword">return</span> Promise <span class="token punctuation">.</span> <span class="token function">reject</span> <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> axios <span class="token punctuation">.</span> interceptors <span class="token punctuation">.</span> response <span class="token punctuation">.</span> <span class="token function">use</span> <span class="token punctuation">(</span> <span class="token punctuation">(</span> <span class="token parameter">response</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle response data</span> <span class="token keyword">return</span> response <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">(</span> <span class="token parameter">error</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// handle response un-authen error</span> <span class="token keyword">if</span> <span class="token punctuation">(</span> error <span class="token punctuation">.</span> response <span class="token punctuation">.</span> status <span class="token operator">===</span> <span class="token number">401</span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">navigate</span> <span class="token punctuation">(</span> <span class="token string">"/login"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> Promise <span class="token punctuation">.</span> <span class="token function">reject</span> <span class="token punctuation">(</span> error <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token operator"><</span> Outlet <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token constant">ALL_ROUTES</span> <span class="token operator">:</span> RouteObject <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token operator">...</span> <span class="token constant">HOME_ROUTES</span> <span class="token punctuation">,</span> <span class="token operator">...</span> <span class="token constant">PRODUCT_ROUTES</span> <span class="token punctuation">,</span> <span class="token operator">...</span> <span class="token constant">CATEGORY_ROUTES</span> <span class="token punctuation">]</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">CONTAINER_ROUTES</span> <span class="token operator">:</span> RouteObject <span class="token punctuation">[</span> <span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> element <span class="token operator">:</span> <span class="token operator"><</span> OutletContainer <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">,</span> children <span class="token operator">:</span> <span class="token constant">ALL_ROUTES</span> <span class="token punctuation">,</span> errorElement <span class="token operator">:</span> <span class="token operator"><</span> ErrorPage <span class="token operator">/</span> <span class="token operator">></span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token function">createBrowserRouter</span> <span class="token punctuation">(</span> <span class="token constant">CONTAINER_ROUTES</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
How to use
1 2 3 4 5 6 | <span class="token keyword">import</span> axios <span class="token keyword">from</span> <span class="token string">'axios'</span> <span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">getProducts</span> <span class="token operator">=</span> <span class="token punctuation">(</span> <span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> axios <span class="token punctuation">.</span> <span class="token function">get</span> <span class="token punctuation">(</span> <span class="token string">"/products"</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> |
summary
That’s it, hope you understand the article.