How to wire react component to redux store

ref – https://eslint.org/docs/rules/object-shorthand

todos

Say we want to add Reporting component to the web app.
We first create the component.
We do a simple return of basic html.

Now that this component exists, we import it into our App file.

You should now see “Testing 1 2 3” in the output.

Adding the reducer

We now add the reducer. The reducer controls the state the data is in. Thus, naturally, we want to have an initial state. We want to say that whatever happens in the app, according to MACROS that gets passed in, we want to return the state of the data.

Thus, we declare the MACROS in the action file. The action file does two things:

1) contain functions that return action objects. Notably, there is a type property in this action object that contains a MACRO. This MACRO describes what kind of action it is.
i.e fetching report has started, fetching report error, fetching report finished.

2) contains the MACRO definition themselves

/src/actions/index.js

and then say if the action type is
this, then we want to return a certain state.

In our case, we have a state where the fetching of the report has just started.
So we want to set the property to certain defaults.

However, notice that the reducer 1st parameter is the initial state. So make sure you set that.

/src/reducers/reportingReducer.js

Add in mapStateToProps and connect

Now we import connect function from redux and use it to connect our component to the store.

Right now, we just simply connected the component to our mapStateToProps.

Hence, when we refresh the web app our output goes in this order:

1) Component initializes with connect function

the connect function gets run first. – √ connect data to Reporting component.

2) Initialize all reducers

all reducers will receive a default action object with a system INIT macro string. You won’t have to worry about it. Your reducers should simply return the initial states. This will happen for all reducers like so:

reducers/todos.js

reducers/reportingReducer.js

reducers/visibilityFilter.js

3) combineReducers

Now that all the reducers have been initialized, the next step is that we use Object Literal Shorthand in order to create an object literal and declare its properties and values.

so for example this:

becomes this:

hence, we create an object literal with all the reducers as properties like so:

then insert it into combineReducers:

src/reducers/index.js

In other words, we created a object literal using short hand notation.
We declare property ‘todos’, and point it to object todos.
We declare property ‘visibilityFilter’ and point it to object visibilityFilter.
We declare property ‘reportingReducer’ and point it to object reportingReducer.

4) createStore

We then pass this temporary object into the createStore parameter. As a result, we get a singleton store. What’s in the store will reflect what’s in this object.

Now, in mapStateToProps of our Reporting component, let’s look at

Now that the reducers were initialized, and the store created, the store state gets passed into our mapStateToProps.

It will be logged as:


{
reportingReducer: {reportingData: null, reportingLoading: false, reportingError: null}
todos: []
visibilityFilter: “SHOW_ALL”
__proto__: Object
}

The reason why it has those properties is because earlier we created an temporary object with data from our reducer files, and initialized the store with it.

5. mapStateToProps

Once we reach this function, we’re literally trying to map the store’s data into Reporting component’s this.props.

Thus, the reportingState should have all the data of the store. You can check by logging reportingState as shown. Before the other functions are called, this mapStateToProps will be executed. You can decide what kind of objects are returned. These returned objects will be reflected in your this.props.

Now when the component refreshes itself by calling render and componentDidLoad, check log your this.props. You’ll see that it has been updated with the store data.


dispatch: ƒ dispatch(action)
reportingReducer: {reportingData: null, reportingLoading: false, reportingError: null}
todos: []
visibilityFilter: “SHOW_ALL”
__proto__: Object

Creating a trigger

In your reporting.js, insert this code. We have inserted an object to represent mapDispatchToProps.

Let’s use this dispatch function in our componentDidMount:

We then execute the action of fetching the reports.

output:
——————-> calling fetchReportingAction
index.js:67 actions/index.js – called fetchReporting

An action will trigger all the reducers via the connect function.
Hence, all of our reducers will check to see they handle the action.type.


todos.js:3 — reducers/todos.js —
todos.js:4 received action:
todos.js:5 Object
todos.js:26 todos.js – no action.type found. default return state
visibilityFilter.js:5 — reducers/visibilityFilter.js —
visibilityFilter.js:11 visibliytFilter.js – no action.type found. default return state

Going through todos and visibilityFilter reducers, we do not handle the specific action.type.
However, in reporting reducer, the action.type matches.

Hence, say we want to update reportingData property with: [‘ricky’, ‘joy’, ‘en en’]
We update it by returning a temp object with the new values.

output:

reportingReducer.js:10 — reducers/reportingReducer.js —
reportingReducer.js:12 received action is:
reportingReducer.js:13 Object
reportingReducer.js:18 — action.type found! –FETCH_REPORTING_STARTED
reportingReducer.js:19 returning state object with updated action.data…

Once the store gets updated, mapStateToProps of our Reporting component is called to let us know we can update our component with whatever data we want from the whole store.

Reporting.js

Take note that parameter storeState has data from the whole store. It looks like this:


reportingReducer: {reportingData: Array(3), reportingLoading: true, reportingError: null}
todos: []
visibilityFilter: “SHOW_ALL”

We need to filter what we want. For example, if we only need reportingReducer for our this.props, then we need to return just that part.

Then the this.props in your render and other component functions would only have data like this:


{reportingData: Array(3), reportingLoading: true, reportingError: null, fetchReportingAction: ƒ}
fetchReportingAction: ƒ ()
reportingData: (3) [“ricky”, “joy”, “en en”]
reportingError: null
reportingLoading: true