Jonathan Small
Jonathan Small

Reputation: 1079

React JS with Redux does not appear to re-render

I am just starting to learn React JS with Redux and have, what I think, is a very easy question to answer. I have the following code:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from "redux";

//
//----------------------------------------------------------------------------------------
//

const initialState = {
  count: 0
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return { ...state, count: state.count + 1 };
    case 'DECREMENT':
      return { ...state, count: state.count - 1 };
    case 'RESET':
      return { ...state, count: state.count = 0 };
  }
}

const store = createStore(reducer);

store.subscribe(() =>
  console.log("subscribe log:",store.getState())
)


const Counter = ({ value, onIncrement, onDecrement, onReset }) => 
(
    <div>
        <h1>{value}</h1>
        <button onClick={onIncrement}>+</button>
        <button onClick={onReset}>Reset</button>
        <button onClick={onDecrement}>-</button>
    </div>
);

const render = () => {
  ReactDOM.render(
     <Counter
        value={ store.getState() }
        onIncrement={ () => store.dispatch({ type: 'INCREMENT' }) }
        onDecrement={ () => store.dispatch({ type: 'DECREMENT'}) }
        onReset={ ()=> store.dispatch({ type: 'RESET'}) }
    />,
    document.getElementById('root')
  );
};

render()

When the code executes, the html is rendered but the value of the state is not displayed within the

tags. When I click on the + button or the - button, I can see the value of state.count increase and decrease by viewing the console. I had expected the value of state.count to display in the

tags but no value is ever displayed.

Any assistance is greatly appreciated.
Thank you.

Upvotes: 0

Views: 89

Answers (1)

AngelSalazar
AngelSalazar

Reputation: 3113

First of all, when using redux your reducers should have a default case where return the initial state

like

const reducer = (state = initialState, action) => {

  switch (action.type) {
    case 'INCREMENT':
      return { 
        ...state, 
        count: state.count + 1 
      }
    case 'DECREMENT':
      return { 
        ...state, 
        count: state.count - 1 
       }
    case 'RESET':
      return { 
        ...state, 
        count: state.count = 0
    }
    default:
      return state
  }
}

another error is that you're passing an object to your counter component,

store.getState() // returns an object

you should change that to

store.getState().count

lastly you are using a funcional component (Counter), this does not have state and does not rerender when your store state changes.

If you want to react to your store changes you have to create a class Component where it subscribes to the store in the componentDidMount lifecycle method and use the setState method to rerender your component.

So in order to show changes you have to call render inside your subscribe function like

const initialState = {
  count: 0
};
const reducer = (state = initialState, action) => {

  switch (action.type) {
    case 'INCREMENT':
      return { 
        ...state, 
        count: state.count + 1 
      }
    case 'DECREMENT':
      return { 
        ...state, 
        count: state.count - 1 
       }
    case 'RESET':
      return { 
        ...state, 
        count: state.count = 0
    }
    default:
      return state
  }
}

const store = Redux.createStore(reducer);



const Counter = (props) => {
  const { value, onIncrement, onDecrement, onReset } = props;
  return (
    <div>
        <h1>{value}</h1>
        <button onClick={onIncrement}>+</button>
        <button onClick={onReset}>Reset</button>
        <button onClick={onDecrement}>-</button>
    </div>
  );
}

const render = () => {
  ReactDOM.render(
    <Counter 
      value={store.getState().count}
      onIncrement={() => store.dispatch({ type : 'INCREMENT' })}
      onDecrement={() => store.dispatch({ type : 'DECREMENT' })}
      onReset={() => store.dispatch({ type : 'RESET' })}
    />,
    document.getElementById('root')
  );
};

store.subscribe(() => {
  console.log(store.getState());
  render();
})
render()

an a demo

Upvotes: 3

Related Questions