Reputation: 61
I can change the store and the state from my component but I cannot access it.
I'm new to programming and I have a problem with React + Redux. My application has a few pages connected with react-router and I use Redux to save the inputs from my form fields.
const insuranceReducer = (state = {
productName: ""
}, action) => {
switch(action.type) {
case "UPDATE_FORM":
if(action.payload.productName){
state = {
...state,
productName: action.payload.productName
}
}
return state;
} }
The store is created with
const store = createStore(insuranceReducer, applyMiddleware(myLogger));
store.subscribe(() => {
console.log("store updated", store.getState());
})
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root'));
And I can change it with a dispatch from the component with this code
const mapDispatchToProps = (dispatch) => {
return {
handleChange: (event) => {
dispatch({
type:"UPDATE_FORM",
payload: {[event.target.name]: event.target.value}
})
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(FormComp);
This works!!! I have an onChange for the input fields and the Middleware in the store console logs the changes. All is good until I try to use mapStateToProps. This gives me undefined for the state. I try to access it with this
const mapStateToProps = state => {
console.log(state);
return {
name: state.productName,
}
}
It gives and error "Cannot read property productName of undefined" and the console log for state is undefined. Please give me some ideas as to why this doesn't work. I have almost the same setup for another project and it is working. Could it be connected to the React Router because I'm not using it in the other project? Dispatching actions to the store works and changes state but I can't access it. Sorry if the post is not very informative, I'm still not used to posting questions.
Upvotes: 1
Views: 395
Reputation: 15708
In your reducer, you are doing a state mutation in the if-block. You want to avoid directly updating the existing state-object. This is against Redux principles. Instead, you should be create a completely new state like so.
const initialState = { productName: "" };
const insuranceReducer = (state = initialState, action) => {
switch (action.type) {
case "UPDATE_FORM":
if (action.payload.productName) {
return {
...state,
productName: action.payload.productName
};
}
return { ...state };
default:
return state;
}
};
export default insuranceReducer;
In order for your connected-component to update correctly with new props, Redux needs to know that you're returning a completely new state. If you do a state-mutation, you're actually updating the same object in reference, and to Redux that does not register as a legal state update.
Additionally, it looks like you never returned a default state for your reducer. If no state is returned, then when you try to access it in mapStateToProps()
, your reducer would just return undefined.
See working sandbox: https://codesandbox.io/s/async-snowflake-tnv0e
Upvotes: 1