mcli_
mcli_

Reputation: 21

Simple React-Redux component not updating

I'm just starting to learn redux with react and I've been having this simple issue for a while now that I can't figure out. I have a button that dispatches an action to increment a value, and the action goes through and updates the state, but no change is ever reflected in the component. What am I doing wrong here?

const ACTION = 'ACTION';
const defaultState = {
  value: 5
};
const doAction = ()=>{
  return {
    type: ACTION
  };
};

const reducer = (state = defaultState, action) => {
  let update = Object.assign({}, state);
  switch(action.type){
    case ACTION:
      update.value = state.value + 1;
      return update;
    default:
      return state;
  }
};

const store = Redux.createStore(reducer);

class App extends React.Component {
  constructor(props){
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e){
    this.props.doAction();
  }

  render(){
    return(
      <div id='app'>
        <button onClick={this.handleClick}>Click</button>
        <p>{this.props.value}</p>
      </div>
    );
  }
}

const Provider = ReactRedux.Provider;

const mapStateToProps = (state)=> {
  return {
    value: state.value
  };
}

const mapDispatchToProps = (dispatch) => {
  return {
    doAction: () => {
      dispatch(doAction())
    }
  };
}

const Container = ReactRedux.connect(mapStateToProps, mapDispatchToProps)(App);

class AppWrapper extends React.Component {
  constructor(props){
    super(props);
  }
  render(){
    return(
      <Provider store={store}>
        <Container />
      </Provider>
    );
  }

}

ReactDOM.render(<AppWrapper />, document.getElementById('root'));

Upvotes: 1

Views: 154

Answers (1)

sn42
sn42

Reputation: 2444

Issue regarding codepen.io

Codepen provides the newest version of react-redux by default, unluckily it is a test version (5.1.0-test.1) currently. Change the external script url of react-redux to https://cdnjs.cloudflare.com/ajax/libs/react-redux/5.0.7/react-redux.js and your pen should be working: Working example

I don't recommend codepen for react development. Consider create-react-app or codesandbox.io if it has to be an online ide. You really need more than one editable file to structure your actions, reducers and components.

How to improve your code

In your reducer you create a copy of the previous state in every case, even when you return the previous state. Try this instead:

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case ACTION:
      return { ...state, value: state.value + 1 };
      // Alternative: Object.assign({}, state, { value: state.value + 1 });
    default:
      return state;
  }
};

This will ensure you create objects only if needed. You could have returned { value: state.value + 1 } for this simple state shape, the spread operator or Object.assign(...) are a valuable tool when you want to clone the previous state and change only some (or delete) properties without affecting others.

Furthermore you can refactor your app to a functional react component:

const App = (props) => (
  <div>
    <button onClick={props.action}>Click</button>
    <p>{props.value}</p>
  </div>
);

And connect the App to redux with:

const mapStateToProps = (state) => ({
  value: state.value
});

const mapDispatchToProps = dispatch => ({
  action: () => dispatch(doAction())
});

const Container = connect(mapStateToProps, mapDispatchToProps)(App);

Note that i stick to your component names here.

Where to go from here...

If you are interested in a bigger example i have created this sandbox which features routing, fake authentication, a todo list and a simple counter. Redux devtools is integrated, too. Just open the browser extension on this site to inspect the store and the dispatched actions.

Upvotes: 1

Related Questions