Releases: react-boilerplate/redux-injectors
v2.1.0
🐛 Bug Fix
- Fixes TS typing for
createManagerso bothreducerandsagaare optional (See #36, thanks @mrfratello !) - Adds support for react 18 in peerDeps (See #42, thanks @partounian !)
v2.0.0
It’s been a long time coming, but redux-injectors 2.0 is here 🎉
This release contains some breaking changes and some new features. Unfortunately some breaking changes were needed in order to fix #19 .
For the announcement blog post, see this link.
💥 Breaking Changes
useInjectReducer
- Reducer injection now happens inside a
useLayoutEffectinstead of during the render. This means the following patterns will be broken:- A
useSelectorcall after a call touseInjectReducerwill result inundefinedfor the first render, if the selector tries to select from a piece of state that the reducer manages. If you need to do this, please make your selector resilient to undefined state. - An injected reducer will not receive a dispatch if that dispatch is made inside a
useLayoutEffectinside a component further down the tree. This can be fixed by any of the following:- Use
useEffectinstead ofuseLayoutEffect useInjectReducernow returns a boolean indicating whether or not the reducer has finished injecting. This allows you to returnnullif the boolean isfalseinstead of the component's children.- Use the new
createManagerAPI which does the above point for you
- Use
- A
useInjectSaga
- Saga injection now happens inside a
useLayoutEffectinstead of during the render. This means the saga will not catch a dispatch made inside auseLayoutEffectinside a component further down the tree. This can be fixed in the same ways as explained in theuseInjectReducersection - The default saga injection mode was changed to
COUNTER. In this mode, the saga will be injected once at-least 1 component mounts that depends on this saga. The saga will be ejected once every component that depends on this saga un-mounts. This means multiple components can inject the saga, but the saga will only run once until every one of these components un-mounts. - The mode parameter for
useInjectSagawas removed. The default and only possible mode for saga injection is nowCOUNTER.
🚀 New Features
createManager
This is a new API that creates a "manager" component given a reducer and/or saga. Each manager will only render its children after both
the reducer and saga has been injected. You can almost think of managers like "providers" for reducers and sagas.
const BooksManager = createManager({ name: "BooksManager", key: "books", reducer: booksReducer, saga: booksSaga })
...
<BooksManager>
<BooksList />
</BooksManager>
This is now the recommended way to use redux-injectors because it avoids some caveats with useInjectReducer and useInjectSaga.
COUNTER mode
The COUNTER mode is a new saga injection mode, and the only mode used by useInjectSaga. This mode is relevant when multiple useInjectSaga are injecting the same saga. When the first useInjectSaga injects, the saga will be run. Each subsequent useInjectSaga will not re-run the saga. The saga will be ejected when the last component using the saga un-mounts.
In other words, this means multiple components can inject the saga, but the saga will only run once until every one of these components un-mounts. Thanks @goranurukalo for the contribution!
📝 Documentation
- A note was added to the documentation recommending to set
shouldHotReload: falsefor redux dev tools. - An example app was added
v2.0.0-rc
This pre-release contains some breaking changes and some new features. Unfortunately some breaking changes were needed in order to fix #19 . Since this is a release candidate, please Install at your own risk. If you do install this version, please report any issues you find.
💥 Breaking Changes
useInjectReducer
- Reducer injection now happens inside a
useLayoutEffectinstead of during the render. This means the following patterns will be broken:- A
useSelectorcall after a call touseInjectReducerwill result inundefinedfor the first render, if the selector tries to select from a piece of state that the reducer manages. If you need to do this, please make your selector resilient to undefined state. - An injected reducer will not receive a dispatch if that dispatch is made inside a
useLayoutEffectinside a component further down the tree. This can be fixed by any of the following:- Use
useEffectinstead ofuseLayoutEffect useInjectReducernow returns a boolean indicating whether or not the reducer has finished injecting. This allows you to returnnullif the boolean isfalseinstead of the component's children.- Use the new
createManagerAPI which does the above point for you
- Use
- A
useInjectSaga
- Saga injection now happens inside a
useLayoutEffectinstead of during the render. This means the saga will not catch a dispatch made inside auseLayoutEffectinside a component further down the tree. This can be fixed in the same ways as explained in theuseInjectReducersection - The default saga injection mode was changed to
COUNTER. In this mode, the saga will be injected once at-least 1 component mounts that depends on this saga. The saga will be ejected once every component that depends on this saga un-mounts. This means multiple components can inject the saga, but the saga will only run once until every one of these components un-mounts. - The mode parameter for
useInjectSagawas removed. The default and only possible mode for saga injection is nowCOUNTER.
🚀 New Features
createManager
This is a new API that creates a "manager" component given a reducer and/or saga. Each manager will only render its children after both
the reducer and saga has been injected. You can almost think of managers like "providers" for reducers and sagas.
const BooksManager = createManager({ name: "BooksManager", key: "books", reducer: booksReducer, saga: booksSaga })
...
<BooksManager>
<BooksList />
</BooksManager>
This is now the recommended way to use redux-injectors because it avoids some caveats with useInjectReducer and useInjectSaga.
COUNTER mode
The COUNTER mode is a new saga injection mode, and the only mode used by useInjectSaga. This mode is relevant when multiple useInjectSaga are injecting the same saga. When the first useInjectSaga injects, the saga will be run. Each subsequent useInjectSaga will not re-run the saga. The saga will be ejected when the last component using the saga un-mounts.
In other words, this means multiple components can inject the saga, but the saga will only run once until every one of these components un-mounts. Thanks @goranurukalo for the contribution!
📝 Documentation
- A note was added to the documentation recommending to set
shouldHotReload: falsefor redux dev tools. - An example app was added
v1.3.0
v1.2.0
v1.0.0
🎉This is our first release of the redux-injectors project 🎉
As some background, redux-injectors was created by pulling out the injectors-related code from the main react-boilerplate repository.
This library lets you dynamically load redux reducers and redux-saga sagas as needed, instead of loading them all upfront. This has some nice benefits, such as avoiding having to manage a big global list of reducers and sagas. It also allows more effective use of code-splitting.