redux-suspense
A redux middleware that lets you use your own data fetching and expose the results in a suspense compatible way
Caution:
- Suspense API is an experimental features that is not yet available in a stable React release.
Basic usage guide
npm install redux-suspense
Step 1 of 4: Suspense reducer
Add the reducer
// src/reducers/index.js
import { combineReducers } from 'redux'
import { suspenseReducer } from 'redux-suspense'
const rootReducer = combineReducers({
// ...your other reducers here
// you have to pass suspenseReducer under 'suspense' key,
suspense: suspenseReducer
})
Step 2 of 4: Suspense middleware
import { createStore, applyMiddleware } from 'redux';
import { suspenseMiddleware } from 'redux-suspense';
import rootReducer from 'src/reducers/index';
const store = createStore(rootReducer, applyMiddleware(suspenseMiddleware));
Step 3 of 4: Create a resource
// src/resources/postsResources.js
import { createResource } from 'redux-suspense';
export const postsResource = createResource(
'POSTS',
fetchPosts, // this is your async function that fetches and returns the posts
)
If you want to store the posts in your own reducer just pass a selector to createResource
. For example:
export const postsResource = createResource(
'POSTS',
fetchPosts,
state => state.yourPostsReducer.posts
)
// Then you can export the success action to handle it in your reducer.
export const { success: fetchPostsSuccess } = postsResource
createResource
will create a couple more things:
-
resourceName
This is the same string you passed as first argument. -
handler
The function you passed as the second argument. -
success
,error
andrequest
These are action creators. All of which have atoString()
method. In the example abovesucces.toString()
would evaluate to'POSTS_SUCCESS'
-
selector
The selector you passed as the third argument.
Step 4 of 4: Consume a resource
Dispatch the resource as an action, as soon as you want to start fetching data. And use useResource
as if it was a selector, inside a <Suspense>
tag.
import React, { Suspense, useEffect } from 'react'
import { useDispatch } from 'react-redux'
import { postsResource } from 'src/resources/postsResources.js'
function App () {
const dispatch = useDispatch()
useEffect(() => dispatch(postsResource), [])
return (
<Suspense fallback={<h1> Loading...</h1>}>
<Posts />
</Suspense>
)
}
import { useResource } from 'redux-suspense'
import { postsResource } from 'src/resources/postsResources.js'
export function Posts() {
const users = useResource(postsResource)
return (
<div>
{posts}
</div>
)
}
Versioning
We use SemVer for versioning. For the versions available, see the tags on this repository.
License
This project is licensed under the ISC License - see the LICENSE file for details