What should be structure of Redux Store? - javascript

Redux.org tells to normalize your state but it creates some confusion.
It tells that we should have State in following format:
{
simpleDomainData1: {....},
simpleDomainData2: {....},
entities : {
entityType1 : {....},
entityType2 : {....}
},
ui : {
uiSection1 : {....},
uiSection2 : {....}
}
}
I can achieve this by two ways.
case 1: I have 3 pages, home, create, feeds page. Hence I can create homeReducer.js, createReducer.js, feedsReducer.js and each reducer will have simpleDomainData1, simpleDomainData2, entities , ui.
case 2: I can create separate reducers for each field like simpleHomeReducer.js, simpleCreateReducer.js, simpleFeedsReducer.js, entitiesReducer, uiReducer.js.
But I am failing to understand, which approach is right, and why ?

Hey kiran as you mentioned in question that you have 2 approaches to structure your reducer.
But, i will give you a new approach.
First of all it's sounds tricky but once you think a little it is
piece of cake for this project and future once also.
You should use combineReducers to combine your reducers to make it easy to use.
1. uiReducer
First you should create reducer for uiSection1 and in it you have all your logic from home Component, create Component and feeds Component for the uiSection1 only.
Just like that you create uiSection2 reducer and in it all your Component logic of your all pages related to uiSection2.
Now combine this 2 reducers to one reducer uiReducer.
2. entityReducer
Now, same thing do with entityType. Create 2 entityType reducer and combine them to one enitityReducer.
3. domainDataReducer
Now create each reducer for domain data and combine it to 1 reducer domainDataReducer
Now you have 3 reducers ui, entity and domainData.
4. rootReducer
Now, combine this 3 reducers to 1 reducer rootReducer and pass it down to index.js
And one last thing, you should do a seperate logic for all your
reducer action. And in this reducer action you can do api call to
backend as well.
This is the link to youtube video by TheNetNinja

There's plenty of information on this at redux.js.org for example basic reducer:
First and foremost, it's important to understand that your entire application really only has one single reducer function: the function that you've passed into createStore as the first argument.
And splitting reducer logic:
For any meaningful application, putting all your update logic into a single reducer function is quickly going to become unmaintainable.
These pages go as far as explaining a variety of techniques to split your reducer logic. There's no "standard" way of breaking reducers so both of your options are acceptable assuming you follow all the other rules of redux reducers.
My opinion
If your reducers are simpler per page, then go for option one. Something like a few actions to manipulate ui, entities and simpleData on each page. Otherwise if you have lots of actions for segments of your data, then split those into their own reducer as you've shown in your option two. For example lots of actions to manipulate ui alone, entities or simpleData.

Related

Are two actions/reducers with the same name permissible in two different reducer files?

I'm curious about something. I was always under the impression that one could have two actions with the same name in two different reducers and that Redux would sort out the correct one to call.
So for example, say you had this setup:
Reducer1: with an UPDATE_TEXT reducer
Reducer2: with an UPDATE_TEXT reducer
And then in your React component file, when you load the correct actions file, it would just know which reducer to call. But testing reveals this not to be the case.
Am I imagining things? Is there a way to isolate and remove such conflicts? Or does one have to carefully never give two disparate reducers the same action name?
Whenever an action is dispatched, all Redux slice reducers are called and given a chance to update their state in response to that action.
Reducers normally inspect the action.type string to decide if they should handle the action, and that is normally done based on an exact string match of the action type:
// switch statements
switch(action.type) {
case 'todos/todoAdded': {}
}
// lookup tables
const caseReducer = caseReducers[action.type];
if (caseReducer) {}
So yes, if multiple reducers are looking for the exact same action type string, they will all end up updating their state in response. This is intentional - we encourage multiple reducers handling the same action.
That also means that if you want to distinguish between multiple actions, you must give each of them a unique type string.
That's why the Redux Toolkit createSlice function accepts a name string - to help make each action type more unique, so that 'sliceA/event' is different than 'sliceB/event'.
(Note that you really should be using Redux Toolkit to write all your Redux logic anyway.)
When you dispatch an action say getData it is normally associated with a type say, GET_DATA. If you name your two actions differently but with the same type, then the reducer would be triggered for all those cases where the type name matches. Thus it is better to carefully name your actions.
I usually prefer using the Ducks pattern for setting up my redux. Thus I prefix all the action type names with the duck name it belongs to. This helps me isolate the actions.
You can look into the following for more
Actions Redux
Ducks Pattern

ReactJS + Redux force reducers to have state in same object-tree

i'm actually working on a ReactJS-Project in combination with Redux.
I did some tests with submitted actions in some different reducers which are combined.
My Problem is that it seems that the reducer only edit its own "scope" inside of my application state. So if i got 2 reducers "ReducerA" and "ReducerB" with some states in it my State tree becomes this:
{
ReducerA:{
stateA: 2
},
ReducerB:{
stateA: 1
}
}
I'll build a initialize reducer which should be able to set information in ReducerA and even in ReducerB. Is that agains the FLUX / REDUX architecture?
Kind regards,
jDoe ;)

Best way to build communication between redux libraries

We are trying to split our project on to pieces:
We have libraries e.g user-library and image-library.
Each library has their own reducer, and actions e.g:
for user-library:
{isloggein: false} // store
function logIn() { //action creator
return {
type: 'LOGIN'
};
}
for image-library:
{images: []} // store
function addImages() { //action creator
return {
type: 'ADDIMAGES'
};
}
Now we decide that we want addImages as soon as user logIn. Problem is image store now nothing about user actions (that is main idea of code splitting). We solved that problem by using sagas like this:
function* addImagesWhenLogIn() {
while (true) {
yield take('LOGIN');
yield put(addImages());
}
}
But it is not opaque (we dispatched one action but 2 actions will be dispatch actually). While it is fine to have business logic of application in sagas, I believe that take -> put sequence is not the best solution in such case, and I am looking for better way of doing it.
Some of the advantages of redux architecture is the capability to easy hydration, snapshots, time travel, and it works best if there is a single place where state is stored.
From redux docs:
Single source of truth - The state of your whole application is stored
in an object tree within a single store. Ref.
Therefore a unique state for your redux app is recommended.
In your case I would suggest:
You could keep separated your libraries/modules, import them as you need in your app.
Use only a single state tree as suggested in redux docs.
Provide state information to your representational components using containers.
I think that's a perfectly valid approach. Your two main options are to either have one module import action creators from the other module (thus somewhat coupling the two directly), or have a separate piece of code that glues the two together. Using a saga like that is a very good approach for handling the "glue" aspect.

react, redux - Modifying parent components with redux

Okay so I had a problem when programming in react, and I've found that it's a common one. If I have multiple nested components, in my case I have:
<AppView>
<Navigation/> // this is a navbar
<ViewHandler currentTab={props.currentTab}/>
<Footer/>
</AppView>
And then in <ViewHandler/> I have other dumb presentational components, which also have nested components as well. If I have a button in a deeply nested component within <ViewHandler>, and I want to respond to onClick from that button by changing something many parent components above the component that I am in, how would I do so? In my case I would be reacting to the button being clicked in that deeply nested component, and then I want to change the selected tab on <Navigation>. I don't want to pass a bunch of callback functions down as properties, because that feels very scotch-tape-ish.
I learned redux because I read that it solved this problem. But for me it hasn't. I am giving <AppView> access to my redux store using react-redux's <Provider>, and I can access the store through props (props.currentTab). But for all the components nested within <AppView>, they don't have access to the store or any of my action creators. How can modify my store from within a deeply nested component so that I may change a parent component without passing a ton of callback functions down? Or is this just incorrect architecture? I thought redux would solve this problem but it hasn't.
Yes I have connected my component. I just don't like the idea of passing down store.state information as props because it gets very redundant with many nested components.
I don't know why you think you have to send props all the way down your component tree. That's what connect and mapStateToProps help you avoid: they let you turn bits of app state into props only for the components which need it.
in your button's onClick handler, create and dispatch a Redux action:
// button.js
onClick={() => {
dispatch({
payload: 1 // or whatever value
type: 'SET_SELECTED_TAB'
});
}}
next, have your reducer function watch for this action and modify a bit of Redux app state:
// reducer.js
if (action.type === 'SET_SELECTED_TAB') {
return {
...currentAppState,
selectedTab: action.payload
};
}
finally, in the render function of your <Navigation> component, you decide which tab to show based on the current values in that bit of app state:
// Navigation.js
render() {
return (
<div>
current tab: {this.props.selectedTab}
</div>
);
}
access to that state is via connect and mapStateToProps:
// Navigation.js still
const mapStateToProps = (appState) => {
return {
selectedTab: appState.selectedTab
};
};
export default connect(mapStateToProps)(Navigation);
Hoc (higher order components) is a wrapper that is serving methods and data to the children components, usually it's a good idea to use it , but it enforces some 'discipline'.
Example: if your HOC is at level 0 and you have a deeply nested button component at level 4 that calls a method in this same HOC , What should you do ? pass it down the to all 4 levels? the answer is NO WAY !
Because doing so will bring the spaghetti to it , Everytime you click this button , and assuming the method binded to it will mess with the state (internal or the store itself) it will rerender all the 4 levels , and you could avoid that by using the shouldComponentUpdate() but this is way too much work for nothing useful.
So the solution would be to connect every component with mapStateToProps and mapDispatchToProps , right ?
well kind of , in fact after using extensively react and redux , you will notice that for every component , there is a sweet spot in terms of size , childrens , and what you should put in it and what you should not.
Example: you have a button inside a form that controls the send mechanism , there's no need to make a component for the button , it will add up complexity without any benefit. just put it on the form component and you will have both ready to use.
If you really need to call actions or to pass props between a deeply nested component and an HOC then use the connect module at the component level (for your case the button) , but not much because it will make your components heavier (to load and to display).Here are some tips to help :
you need to be as specfic as possible when you use mapStateToProps , don't return the whole store , just the piece of data needed , same for mapDispatchToprops , just bind the method that you will be using nothing else.
in your case the button doesn't have to know which tab is selected , so a mapDispatchToProps is enough.
avoid deep nesting components that handles some kind of logic ,refactor your structure or create A HOC for that component , logic less components in contrary can be nested deeply
If you are writing a huge app with a lot of reducers and states , consider using selectors , and some libraries like reselect.
I know that this is not the answer you were expecting but following this guideline will saves you countless hours of refactoring.
Hope it helps

Replacing entire tree item in Redux with different reducer

Given the following redux state tree:
{
app: {...},
config: {...},
page_data: {...}
}
How would I replace the contents of page_data with an entire separate reducer depending on the page a user is on?
For example I could have three reducers user, products, competitions. If I switched from a user page to a product page I'd want the page_data branch to show:
{
page_data: {
productPage: {...}
}
}
with no reference to user as I don't want to bloat the app state and also don't need that data on the product page.
Note: I'm using combineReducers for reference.
Is this possible and what is the best approach?
Using same name for multiple reducers is definitely wrong. Not just it isn't supported, it's wrong practice. You can achieve this using FLUSH_PAGE_DATA action. Dispatching this action will flush the page data in all the reducers. It'll Look something like this.
case 'FLUSH_PAGE_DATA':
return { };
Then based on you active page, which you'll pass in every action, you can create different structure of page data.

Categories

Resources