I am trying out React/Redux/JS for the first time. I am a little confused about setting state in component vs letting redux update it.
I want to click a button to set the lightOn to true and have the updated this.props.lightOn value display. I am missing something fundamental but not sure what.
action:
export const setLight = lightStatus => dispatch => {
const res = lightStatus;
console.log(res); // => true on click
dispatch({ type: SET_LIGHT, payload: res });
};
In the component, {this.props.onLight} is undefined so I am not updating state correctly:
import React, { Component } from 'react';
import { connect } from 'react-redux';
//import * as actions from '../actions';
import { setLight } from '../actions';
import { bindActionCreators } from 'redux';
class Light extends Component {
render() {
return (
<div>
Light Status: {this.props.lightOn}
<button
className="btn"
onClick={() => this.props.setLight(true)}
>
Set Light!
</button>
</div>
);
}
}
function mapStateToProps(state) {
return {
lightOn: state.lightOn
};
}
function mapDispatchToProps(dispatch) {
//whenever selectBook is called the result should be passed to all of our reducers
return bindActionCreators({ setLight: setLight }, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Light);
the reducer (updated with spread operator):
import { SET_LIGHT } from '../actions/types';
export default function(state = [], action) {
switch (action.type) {
case SET_LIGHT:
return { ...state, lightOn: action.payload };
default:
return state;
}
}
the wrong on the reducer, the reducer should return the state object with lightOn key, but you return payload value, and this is the issue. your reducer should return lightOn with payload value like this.
How about set it as a state instead of pass direct to the function ? First binding it inside Constructor and then on click setState to true ?
As you are using redux , you can do it this way by returning a fresh state instead
How it works? Through
connect
you can inject props that are used to control redux state and bind it to the component. For example:In given example you are binding
someReduxState
part of state tostateProp
, which is injected into component. You are injecting method (sendSomething
) that will dispatch and action in redux. If component relays on displaying part of redux state, it will be updated each time redux state changes, because props that are injected to component will change. You can find more in official Redux documentation here, or you can watch free tutorial on egghead here.Instead of setting state with array I am now setting with object. I guess I was putting lightOn object in light array which was making it inaccessible.
action:
reducer:
the component:
You are not returning a new state here
You're directly returning
action.payload
which is simplylightStatus
Which means you can't access
state.lightOn
in yourmapStateToProps
Your should be doing
Or directly
This way the entire state is not lost and its not directly mutating the state. Here i am using the object spread operator instead of Object.assign for the sake of simpicity.