I have theses files :
numPadHandler (my reducer), configureStore (my store), TestRedux (my component, trying to use the store) and my app file.
reducer :
// store/reducers/numpadReducers/numpadHandler
const initialState = { valueNumPad: "1" }
function numpadHandler(state = initialState, action) {
let nextState;
switch(action.type) {
case 'ADD_DIGIT':
nextState = state;
nextState.valueNumPad = nextState.valueNumPad + action.value;
console.log("reducer new state : " + state.valueNumPad);
return nextState;
default:
return state;
}
}
export default numpadHandler;
store :
// store/configureStore
import { createStore } from 'redux';
import numpadHandler from './reducers/numpadReducers/numpadHandler';
export default createStore(numpadHandler);
component :
// components/TestRedux
import React, { useState } from "react";
import { connect } from 'react-redux';
import Button from './Button';
const TestRedux = (props) => {
const handleClick = () => {
console.log("props value numpad : " + props.valueNumPad);
const action = { type: "ADD_DIGIT", value: 5 }
props.dispatch(action);
}
return (
<div>
<Button onClick={handleClick} />
</div>
);
}
const mapStateToProps = (state) => {
console.log("state : " + state.valueNumPad);
return state
}
export default connect(mapStateToProps)(TestRedux);
app :
//...
render() {
return (
<Provider store={ Store }>
<TestRedux />
</Provider>
);
}
I can't figure why when i click on the button, the reducer's state is changing but the function mapStateToProps isn't called again.
There is my console output after page load :
state : 1
After one click :
props value numpad : 1
reducer new state : 15
After two click :
props value numpad : 1
reducer new state : 155
Complete console output after 2 clicks :
state : 1
props value numpad : 1
reducer new state : 15
props value numpad : 1
reducer new state : 155
So you can see the action is happening and the reducer state is updating, but there is not update in component side !
Can you explain me why ?
RESOLVED : Answer based on TLadd response :
My reducer code was wrong, this is the good way to code :
case 'ADD_DIGIT':
const nextState = {
...state,
valueNumPad: state.valueNumPad + action.value
};
return nextState
The problem is in the reducer:
Redux works off the assumption that all state changes are handled immutably. This choice allows it to use shallow equality checks when deciding which parts of your app need to re-render in response to an action being dispatched. In the above reducer case, you assign state to nextState and assign the new value directly to
nextState.valueNumPad
. Even thoughnextState
is a new reference, it still refers to the original state as well and the result is a mutation of the original state.The correct would to do this would be:
In this case, I'm making a copy of state using the spread notation
...state
and overwriting thevalueNumPad
value in that copy. The returnednextState
is a new object and I did not mutate the oldstate
object at all.