Introduce Redux local state to your React App – t-benze – Medium

Introduce Redux local state to your React App  #redux #react #reactjs

  • In this way I can extract the data fetching logic into actions and reducers, and take them out from the component to make sure the component is only dealing with UI stuff, and let actions and reducers handle the business logic.So narrow down the problem, what I want is the capability to create local state that is bound to an component in the redux store, which only lives within the component’s lifecycle, and still enjoy the benefits redux has provided (actions, reducers, middleware).
  • Our requirements are as follows:the component using local state should be able to access the global redux state naturallythe api to connect to local state should be similar as the connect function from react-reduxthe actions dispatched for local state need to work normally with redux middlewarethe actions and reducers need to be agnostic to whether they’re used with respect to local state or global stateImplementationThe local state in redux can be implemented as an add-on to redux quite straightforwardly.
  • To fix this, we create another middleware to apply after the redux thunk middleware.Since the actions dispatched by the local mapDispatchToProps will be scoped like the one below, redux thunk will now handle it and then our middleware will get to handle it, and if we see the localAction is a function, then we call the function as what thunk would do, but pass in the a localDispatch function and a localGetState function as the first two parameters, followed by dispatch and getState function for global state.
  • { type: ‘$LOCAL_DISPATCH_ACTION’, localAction: (localDispatch, localGetState) = {…}, id}ExampleBelow shows a simple app that has one counter reducer in the global state, along with a local reducer, which is empty at the beginning.Once we click show local to create a component that has its local state and reuse the counter reducer, an new state instance with unique id is registered in the local reducer.Within the component, we can dispatch both global actions and local actions, and they won’t affect each others.Once we remove the component, its local state will get discarded the state management in our app is a mixture of different approaches.
  • We have some UI components using setState() to mange their internal UI state that doesn’t concern others, we have some global application state like user info stored in the global redux store, and we also have some page containers which store its feature data in its local redux state.

I’ve been using redux in my recent projects, including both react web and react-native, and I really like its way of managing application state: one single data source, using actions and reducers to…

@_adeeb: Introduce Redux local state to your React App #redux #react #reactjs

I’ve been using redux in my recent projects, including both react web and react-native, and I really like its way of managing application state: one single data source, using actions and reducers to transform state, and support async actions with middleware like redux-thunk.

But gradually one problem starts to bother me, the stuff in the Redux store is always growing and never gets cleared. And with more and more features getting in, this is getting worse and worse. Unlike those demo apps which usually have one or two features, real application tends to have dozens of features grouped by different modules.

Take the typical e-commercial app Amazon for example, when you open the side menu, you can count about 10 entries in the first layer, and some may have a second layer which has another dozen of entries. Each of these entries correspond to one feature and may end up as one slice-reducer in redux. You can imagine how big a tree the state will become. This doesn’t feel right, since by right at any point of time only those state that are related to the current screen need to be “active” (in the state).

So if we don’t want some state data to be kept in redux all the time, the naivest way to go is to use component setState(), and according to the redux doc, this is totally fine. However, relying on component to manage state eventually would make the component very complicated. Usually I’d prefer to keep only the UI state in component, things like input value, dropdown showing flag, etc, and keep the data fetched from server in the redux store. In this way I can extract the data fetching logic into actions and reducers, and take them out from the component to make sure the component is only dealing with UI stuff, and let actions and reducers handle the business logic.

So narrow down the problem, what I want is the capability to create local state that is bound to an component in the redux store, which only lives within the component’s lifecycle, and still enjoy the benefits redux has provided (actions, reducers, middleware). Checking the redux website, there’re already several implementation of this idea, such as redux-ui, redux-react-local, redux-state. But their implementation doesn’t fit very well with our app, so I ended up crafting my own, redux-local-state.

Our requirements are as follows:

The local state in redux can be implemented as an add-on to redux quite straightforwardly. First of all, we need a reducer that handles 3 actions:`LOCAL_REGISTER_STATE`, `LOCAL_DISPATCH_ACTION`, `LOCAL_DISCARD_STATE`.

parameters as connect expects, and one more object as follow to configure the local state.

reducer,

mapStateToProps: (localState) => {…},

mapDispatchToProps: {localActions},

So we first need to pass in a local reducer to handle the local actions. And we need local mapStateToProps function to pick data from the local state into the component props, and a local mapDispatchToProps which automatically scope the actions to be local actions.

Now those actions set in our local mapDispatchToProps will be correctly scoped to the local state. Since we’re using the redux-thunk middleware, we can also dispatch functions from the local mapDispatchToProps, and, within the function we dispatch, we might need to dispatch other actions. By right we would want these actions to be local as well, but the thunk middleware will not scope these actions for sure. To fix this, we create another middleware to apply after the redux thunk middleware.

Since the actions dispatched by the local mapDispatchToProps will be scoped like the one below, redux thunk will now handle it and then our middleware will get to handle it, and if we see the localAction is a function, then we call the function as what thunk would do, but pass in the a localDispatch function and a localGetState function as the first two parameters, followed by dispatch and getState function for global state.

type: ‘$LOCAL_DISPATCH_ACTION’,

localAction: (localDispatch, localGetState) => {…},

reducer, which is empty at the beginning.

to create a component that has its local state and reuse the counter reducer, an new state instance with unique id is registered in the local reducer.

Within the component, we can dispatch both global actions and local actions, and they won’t affect each others.

Once we remove the component, its local state will get discarded automatically.

Eventually the state management in our app is a mixture of different approaches. We have some UI components using setState() to mange their internal UI state that doesn’t concern others, we have some global application state like user info stored in the global redux store, and we also have some page containers which store its feature data in its local redux state. So far things are working well, and since the implementation of actions and reducers don’t care whether they are for local state or global state, it’s quite easy to do the switch. Simply inject them into different places then the component will work seamlessly.

If you’re interested, please try it out here.

Introduce Redux local state to your React App – t-benze – Medium