A redux middleware that lets you use your own data fetching and expose the results in a suspense compatible way
- Suspense API is an experimental features that is not yet available in a stable React release.
npm install redux-suspense
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
})
import { createStore, applyMiddleware } from 'redux';
import { suspenseMiddleware } from 'redux-suspense';
import rootReducer from 'src/reducers/index';
const store = createStore(rootReducer, applyMiddleware(suspenseMiddleware));
// 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.
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 posts = useResource(postsResource)
return (
<div>
{posts}
</div>
)
}
We use SemVer for versioning. For the versions available, see the tags on this repository.
This project is licensed under the ISC License - see the LICENSE file for details