Skip to main content

14.14 Updating State Immutably

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";

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}>Store Result</button>
<ul>
{this.props.storedResults.map((strResult) => (
<li key={strResult.id} onClick={this.props.onDeleteResult}>
{strResult.value}
</li>
))}
</ul>
</div>
);
}
}

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

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

reducer.js

reducer.js
const initialState = {
counter: 0,
results: [],
};

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

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

case "SUBTRACT":
return {
...state,
counter: state.counter - action.value,
};
case "STORE_RESULT":
return {
...state,
results: state.results.concat({ id: new Date(), value: state.counter }),
};
default:
}
return state;
};

export default reducer;