docs: improved documentation

This commit is contained in:
arthurfiorette 2022-05-15 19:54:25 -03:00
parent e97a51585a
commit 6bcd7dca08
No known key found for this signature in database
GPG Key ID: 9D190CD53C53C555
8 changed files with 210 additions and 32 deletions

View File

@ -7,17 +7,21 @@
align-items: center; align-items: center;
font-size: 20px; font-size: 20px;
} }
rk-embed { rk-embed {
width: 100%; width: 100%;
} }
h1.not-found { h1.not-found {
display: inline-block; display: inline-block;
border-right: 1px solid rgba(0, 0, 0, 0.3); border-right: 1px solid rgba(0, 0, 0, 0.3);
padding-right: 1rem; padding-right: 1rem;
margin-right: 1rem; margin-right: 1rem;
margin-bottom: 6rem; margin-bottom: 6rem;
margin-top: 2.5rem !important;
vertical-align: top; vertical-align: top;
} }
h1.not-found__text { h1.not-found__text {
display: inline-block; display: inline-block;
padding-right: 1rem; padding-right: 1rem;
@ -34,10 +38,15 @@
// Write some code in the meantime :) // Write some code in the meantime :)
const Axios = require('axios'); const Axios = require('axios');
const { setupCache, buildWebStorage } = require('axios-cache-interceptor'); const { setupCache } = require('axios-cache-interceptor');
const axios = Axios.create({}); const axios = Axios.create({
setupCache(axios, {}); //
});
setupCache(axios, {
//
});
await axios.get('https://jsonplaceholder.typicode.com/posts/1'); await axios.get('https://jsonplaceholder.typicode.com/posts/1');
``` ```

View File

@ -1,10 +1,11 @@
- Getting Started - Getting Started
- [Homepage](/ 'Homepage') - [Introduction](/ 'Introduction')
- [Installing](pages/installing.md 'Installing') - [Installing](pages/installing.md 'Installing')
- [Configuration](pages/configuration.md 'Configuration') - [Configuration](pages/configuration.md 'Configuration')
- [Storages](pages/storages.md 'Custom storages') - [Storages](pages/storages.md 'Custom storages')
- [Request Id](pages/request-id.md 'Request Id') - [Request Id](pages/request-id.md 'Request Id')
- [Invalidating Cache](pages/invalidating-cache.md 'Invalidating Cache')
- [Development mode](pages/development-mode.md 'Development mode') - [Development mode](pages/development-mode.md 'Development mode')
- API Reference - API Reference

View File

@ -82,7 +82,10 @@
<title>Axios Cache Interceptor</title> <title>Axios Cache Interceptor</title>
<!-- Docsify styles --> <!-- Docsify styles -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css"> <link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/docsify-themeable@0/dist/css/theme-simple.css"
/>
<link <link
rel="stylesheet" rel="stylesheet"
@ -117,6 +120,5 @@
crossorigin crossorigin
src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-jsx.min.js" src="https://cdn.jsdelivr.net/npm/prismjs@1/components/prism-jsx.min.js"
></script> ></script>
</body> </body>
</html> </html>

View File

@ -3,7 +3,7 @@ window.$docsify = {
loadSidebar: 'config/sidebar.md', loadSidebar: 'config/sidebar.md',
notFoundPage: 'config/404.md', notFoundPage: 'config/404.md',
homepage: 'pages/homepage.md', homepage: 'pages/introduction.md',
subMaxLevel: 2, subMaxLevel: 2,

View File

@ -6,7 +6,7 @@
> >
> Please, don't hesitate to open an PR with your own examples and use cases. > Please, don't hesitate to open an PR with your own examples and use cases.
## Nodejs server example ## Nodejs Server
An **NodeJS** with **ExpressJS** example to return data from another api. An **NodeJS** with **ExpressJS** example to return data from another api.
@ -60,32 +60,54 @@ app.get('/cache/:id/get', async (req, res) => {
app.listen(3000); app.listen(3000);
``` ```
## Jsx component example ## React Component
You shouldn't > You shouldn't
[store cache in state libraries](https://betterprogramming.pub/why-you-should-be-separating-your-server-cache-from-your-ui-state-1585a9ae8336), > [store cache in state libraries](https://betterprogramming.pub/why-you-should-be-separating-your-server-cache-from-your-ui-state-1585a9ae8336),
it even is a bad practice. And even if you do so, you probably will have to write a lot of > it even is a bad practice. And even if you do so, you are going to write a lot of error
code to handle cache invalidation, strategies and etc. > prone code to handle cache invalidation, caching strategies and so on.
With this library, you can just call any axios method without worrying about requesting I'm also the maintainer of
thousands of times for every component draw. Simple as that! [`Axios Cache Hooks`](https://tinylibs.js.org/packages/axios-cache-hooks/), a
[**950B**](https://bundlephobia.com/package/axios-cache-hooks) library that just provide
you a simple and complete react hook to use with your axios cached instance.
It is a super powerful hook, because it will share the same updatable piece of data for
every request with the same [id](pages/request-id.md). By using a
[web storage](pages/storages.md?id=Web-storage) with it, you are up to **share component
level data in a micro frontend scale**.
```ts
import Axios from 'axios';
import { createAxiosHooks } from 'axios-cache-hooks';
import { setupCache } from 'axios-cache-interceptor';
const axios = setupCache(Axios);
const { useQuery, useMutation } = createAxiosHooks();
```jsx
function Component() { function Component() {
// React component state (but can be from any other framework, library and etc) const [user, { loading, error }] = useQuery<User>(() => axios.get('/users/123'));
const [data, setData] = useState(null);
// Calling this function every component redraw does not have any if (loading)
// problems, as the response is cached in the first request. This return (
// even work with concurrent requests and for many components at <div class=":)">
// the same time <p>Loading...</p>
axios.get('https://api.example.com').then((response) => { </div>
setData(response.data); );
});
if (error) {
console.error(error);
return (
<div class=":(">
<p>Error!</p>
</div>
);
}
return ( return (
<div class=":)"> <div class=":)">
<div>{data}</div> <div>{user.name}</div>
</div> </div>
); );
} }

View File

@ -10,3 +10,11 @@ Axios Cache Interceptor can be understood as an intermediary that will analyze e
request made, check if no similar request has been made before, if so, return it, if not, request made, check if no similar request has been made before, if so, return it, if not,
wait for the response, warn other requests if they are waiting and return the response to wait for the response, warn other requests if they are waiting and return the response to
the original caller. the original caller.
## Where to start
- [Installing](pages/installing.md)
- [Configuration](pages/configuration.md)
- [Per request configuration](pages/per-request-configuration)
- [A NodeJS Server example](pages/examples?id=nodejs-server)
- [A React Component example](pages/examples?id=react-server)

View File

@ -0,0 +1,132 @@
# Invalidating Cache
A common problem when using a cache-first approach in your client is that there will be
times when your server has newer data, your user knows that it has, but their client
doesn't.
Here's a simple step to step example of it.
1. User list all available posts, server return an empty array.
2. User proceeds to create a new post, server returns 200 OK.
3. Your frontend navigates to the post list page.
4. The post list page still shows 0 posts because it has a fresh cache for that request.
5. User gets angry that the post list page is empty, they click the refresh button.
6. The in-memory cache is vanished and the post list page now shows the created post.
## How to fix it
> You should be familiar with the [Request ID](pages/request-id.md) concept.
There is a [`cache.update`](pages/per-request-configuration.md?id=cacheupdate) option
available for every request that you make. You can resolve this problem in two "major"
ways:
**In these examples, we'll wrap the `list-posts` and `create-post` calls inside known
functions, thus, centralizing the api logic into a single function.**
### Updating the local cache
When you are calling a `create-post` endpoint, it's almost sure that, if the request
succeed, your `list-posts` cache will get out of date.
You can update your `list-posts` cache by using the `cache.update` option in yours
`create-post` requests.
By default, you only need to know the id of the `list-posts` request. There's many ways to
get that information, either by saving the `response.id` in a object or manually defining
the `config.id` in each request.
> This method only works when you are manually making a known request out of date by
> calling another endpoint of your API. Similarly with a `list-posts` and a `create-post`
> request.
```js
function listPosts() {
return axios.get('/posts', {
id: 'list-posts'
});
}
function createPost(data) {
return axios.post('/posts', data, {
cache: {
update: {
// Will perform a cache update for the `list-posts` internal cache
'list-posts': (cachedState, createPostResponse) => {
// If the cache is not cached, we don't need to update it
if (cachedState.state !== 'cached') {
return 'ignore';
}
// Imagine the server response for the `list-posts` request is: { posts: Post[]; }
// And the `create-post` response comes with the newly created post.
// Add the current created post to the end of the post's list
cachedState.data.posts.push(createPostResponse.data);
// Return the same cache state, but a updated one.
return cachedState;
}
}
}
});
}
```
If you want to update the cache for a specific request outside of the request config, you
can use the storage api.
```ts
if (someLogicThatShowsIfTheCacheShouldBeUpdated) {
const cache = await axios.storage.get('list-posts');
// Edits the current cache
cache.data = '...';
await axios.storage.set('list-posts', cache);
}
```
Then, every time you create a post, your listPosts function will - without contacting the
server - return the updated list of posts.
### Invalidating the local cache
This method works by completely erasing the local cache and forcing the client, (whenever
needed) request again to your endpoint.
There's about 3 situations that makes this method better than the previous one:
- When you cannot predict the entire data needed.
- When you know that there is newer data available made by another user or service.
- When the data is too bigger or complex to you handle it in your client without the need
of duplicating hundreds of service classes.
```js
function listPosts() {
return axios.get('/posts', {
id: 'list-posts
});
}
function createPost(data) {
return axios.post('/posts', data, {
cache: {
update: {
// Will erase the list-posts cache and force the client (when needed) request to the server again
'list-posts': 'delete'
}
}
});
}
```
If you want to invalidate the cache for a specific request outside of the request config,
you can use the storage api.
```ts
if (someLogicThatShowsIfTheCacheShouldBeInvalidated) {
// Deletes the current cache
await axios.storage.remove('list-posts');
}
```

View File

@ -1,14 +1,18 @@
# Request id # Request id
A good thing to know is that every request passed through this interceptor, has an id. Every request passed through this interceptor, has an id. **This doesn't mean its a UNIQUE
**This does not mean that is a unique id**. The id is used in a number of ways, but the ID**.
most important is to bind a request to its cache.
Each request id are responsible for binding a request to its cache, for referencing (or
invalidating) it later and to make the interceptor treat each request with the same id as
the same request.
The id generation is good enough to generate the same id for theoretically sames requests. The id generation is good enough to generate the same id for theoretically sames requests.
A simple example is a request with `{ baseURL: 'https://a.com/', url: '/b' }` results to A simple example is a request with `{ baseURL: 'https://a.com/', url: '/b' }` results to
the same id with `{ url: 'https://a.com/b/' }`. the same id with `{ url: 'https://a.com/b/' }`.
Also, a custom id can be used to treat two requests as the same. > If you send two completely different requests with the same id, the interceptor will
> treat them as the same request, sharing its cache and every other as.
```js #runkit ```js #runkit
const axios = require('axios'); const axios = require('axios');