Skip to content

Releases: react-boilerplate/redux-injectors

v2.1.0

22 Nov 13:17
9fae3c1
Compare
Choose a tag to compare

🐛 Bug Fix

  • Fixes TS typing for createManager so both reducer and saga are optional (See #36, thanks @mrfratello !)
  • Adds support for react 18 in peerDeps (See #42, thanks @partounian !)

v2.0.0

30 May 02:00
ff48adf
Compare
Choose a tag to compare

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 useLayoutEffect instead of during the render. This means the following patterns will be broken:
    • A useSelector call after a call to useInjectReducer will result in undefined for 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 useLayoutEffect inside a component further down the tree. This can be fixed by any of the following:
      • Use useEffect instead of useLayoutEffect
      • useInjectReducer now returns a boolean indicating whether or not the reducer has finished injecting. This allows you to return null if the boolean is false instead of the component's children.
      • Use the new createManager API which does the above point for you

useInjectSaga

  • Saga injection now happens inside a useLayoutEffect instead of during the render. This means the saga will not catch a dispatch made inside a useLayoutEffect inside a component further down the tree. This can be fixed in the same ways as explained in the useInjectReducer section
  • 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 useInjectSaga was removed. The default and only possible mode for saga injection is now COUNTER.

🚀 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: false for redux dev tools.
  • An example app was added

v2.0.0-rc

11 Jun 00:40
8dac91d
Compare
Choose a tag to compare
v2.0.0-rc Pre-release
Pre-release

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 useLayoutEffect instead of during the render. This means the following patterns will be broken:
    • A useSelector call after a call to useInjectReducer will result in undefined for 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 useLayoutEffect inside a component further down the tree. This can be fixed by any of the following:
      • Use useEffect instead of useLayoutEffect
      • useInjectReducer now returns a boolean indicating whether or not the reducer has finished injecting. This allows you to return null if the boolean is false instead of the component's children.
      • Use the new createManager API which does the above point for you

useInjectSaga

  • Saga injection now happens inside a useLayoutEffect instead of during the render. This means the saga will not catch a dispatch made inside a useLayoutEffect inside a component further down the tree. This can be fixed in the same ways as explained in the useInjectReducer section
  • 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 useInjectSaga was removed. The default and only possible mode for saga injection is now COUNTER.

🚀 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: false for redux dev tools.
  • An example app was added

v1.3.0

27 Jan 15:34
f4accd7
Compare
Choose a tag to compare

This is a maintenance release.

v1.2.0

24 Oct 14:34
62d836c
Compare
Choose a tag to compare

This release contains a minor fix to update the injection to happen earlier, fixing some race conditions. (See #5)

Note: v1.1.0 does not exist due to a release hick-up

v1.0.0

23 Sep 14:29
ed31c50
Compare
Choose a tag to compare

🎉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.

  • You can read more about the motivation behind this library here
  • And the initial issue leading to the creation of this library here
  • And the api reference docs here