Skip to main content

14.18 Combining Multiple Reducers

index.js

index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { combineReducers, createStore } from "redux";
import App from "./App";
import "./index.css";
import registerServiceWorker from "./registerServiceWorker";
import counterReducer from "./store/reducers/counter";
import resultReducer from "./store/reducers/result";

const rootReducer = combineReducers({
ctr: counterReducer,
res: resultReducer,
});

const store = createStore(rootReducer);

ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
registerServiceWorker();

Counter.js

Counter.js
import React, { Component } from "react";
import { connect } from "react-redux";
import CounterControl from "../../components/CounterControl/CounterControl";
import CounterOutput from "../../components/CounterOutput/CounterOutput";
import * as actionTypes from "../../store/actions";

class Counter extends Component {
render() {
return (
<div>
<CounterOutput value={this.props.ctr} />
<CounterControl
label="Increment"
clicked={this.props.onIncrementCounter}
/>
<CounterControl
label="Decrement"
clicked={this.props.onDecrementCounter}
/>
<CounterControl label="Add 5" clicked={this.props.onAddCounter} />
<CounterControl
label="Subtract 5"
clicked={this.props.onSubtractCounter}
/>
<hr />
<button onClick={() => this.props.onStoreResult(this.props.ctr)}>
Store Result
</button>
<ul>
{this.props.storedResults.map((strResult) => (
<li
key={strResult.id}
onClick={() => this.props.onDeleteResult(strResult.id)}
>
{strResult.value}
</li>
))}
</ul>
</div>
);
}
}

const mapStateToProps = (state) => {
return {
ctr: state.ctr.counter,
storedResults: state.res.results,
};
};

const mapDispatchToProps = (dispatch) => {
return {
onIncrementCounter: () => dispatch({ type: actionTypes.INCREMENT }),
onDecrementCounter: () => dispatch({ type: actionTypes.DECREMENT }),
onAddCounter: () => dispatch({ type: actionTypes.ADD, value: 5 }),
onSubtractCounter: () => dispatch({ type: actionTypes.SUBTRACT, value: 5 }),
onStoreResult: (result) =>
dispatch({ type: actionTypes.STORE_RESULT, result: result }),
onDeleteResult: (id) =>
dispatch({ type: actionTypes.DELETE_RESULT, resultElId: id }),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Counter);

New counter.js

counter.js
import * as actionTypes from "../actions";

const initialState = {
counter: 0,
};

const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.INCREMENT:
const newState = Object.assign({}, state);
newState.counter = state.counter + 1;
return newState;
case actionTypes.DECREMENT:
return {
...state,
counter: state.counter - 1,
};

case actionTypes.ADD:
return {
...state,
counter: state.counter + action.value,
};

case actionTypes.SUBTRACT:
return {
...state,
counter: state.counter - action.value,
};
default:
}
return state;
};

export default reducer;

New result.js

result.js
import * as actionTypes from "../actions";

const initialState = {
results: [],
};

const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.STORE_RESULT:
return {
...state,
results: state.results.concat({ id: new Date(), value: action.result }),
};
case actionTypes.DELETE_RESULT:
// const id = 2;
// const newArray = [...state.results];
// newArray.splice(id, 1);
const updatedArray = state.results.filter(
(result) => result.id !== action.resultElId
);
return {
...state,
// results: newArray,
results: updatedArray,
};
default:
}
return state;
};

export default reducer;

Remove reducers.js