React-redux component does not rerender on store state change

62,889

Solution 1

Your component is only going to re-render if its state or props are changed. You are not relying on this.state or this.props, but rather fetching the state of the store directly within your render function.

Instead, you should use connect to map the application state to component props. Component example:

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';

export class App extends React.Component {
    constructor(props, context) {
        super(props, context);
    }

    render() {
        return (
            <div>
            {this.props.isLoggedIn ? 'Logged In' : 'Not Logged In'}
            </div>
        );
    }
}

App.propTypes = {
    isLoggedIn: PropTypes.bool.isRequired
};

function mapStateToProps(state, ownProps) {
    return {
        isLoggedIn: state.isLoggedIn
    };
}

export default connect(mapStateToProps)(App);

In this very simplified example, if the store's isLoggedIn value changes, it will automatically update the corresponding prop on your component, which will cause it to render.

I suggest reading the react-redux docs to help you get started: https://redux.js.org/basics/usage-with-react

Solution 2

I ended up here because I had written a bad reducer. I had:

const reducer = (state=initialState, action) => {
  switch (action.type) {
    case 'SET_Q':
      return Object.assign(state, {                     // <- NB no {}!
        q: action.data,
      })

    default:
      return state;
  }
}

I needed:

const reducer = (state=initialState, action) => {
  switch (action.type) {
    case 'SET_Q':
      return Object.assign({}, state, {                 // <- NB the {}!
        q: action.data,
      })

    default:
      return state;
  }
}
Share:
62,889
Zalaboza
Author by

Zalaboza

SMILEUPPS-6819DD0DE1

Updated on November 21, 2020

Comments

  • Zalaboza
    Zalaboza over 3 years

    I'm stating to learn react and redux today, yet I cannot figure out how to force component to rerender after state change.

    Here is my code:

    const store = createStore(loginReducer);
    export function logout() { return {type: 'USER_LOGIN'} }
    export function logout() { return {type: 'USER_LOGOUT'} }
    export function loginReducer(state={isLogged:false}, action) {
      switch(action.type) {
        case 'USER_LOGIN':
          return {isLogged:true};
        case 'USER_LOGOUT':
          return {isLogged:false};
        default:
    
    
             return state;
          }
        }
    
        class App extends Component {
    
          lout(){
            console.log(store.getState()); //IT SHOW INITIAL STATE
            store.dispatch(login());
            console.log(store.getState()); //IT SHOWS THAT STATE DID CHANGE
          }
    
          ////THIS IS THE PROBLEM, 
        render(){
        console.log('rendering')
        if(store.getState().isLogged){
          return (<MainComponent store={store} />);
        }else{
          return (
            <View style={style.container}>
              <Text onPress={this.lout}>
              THE FOLLOWING NEVER UPDATE :( !!{store.getState().isLogged?'True':'False'}</Text>
              </View>
            );
        }    
    }
    

    The only way i could trigger update is by using

    store.subscribe(()=>{this.setState({reload:false})});
    

    inside constructor, so that i manually trigger an update state of component to force rerender.

    but how can i link both store and component states ?

  • Kenny Worden
    Kenny Worden over 7 years
    Is App.propTypes required to use connect()? It looks like you just threw that in there.
  • Harold Castillo
    Harold Castillo almost 7 years
    Thanks you so much!
  • Young
    Young almost 4 years
    @KennyWorden I know it's probably too late for an answer. But no, you don't need propTypes. PropTypes are just type declaration for variables. They do not serve any other purpose here while thunk middleware is require to use the connect function. daveceddia.com/what-is-a-thunk
  • Hanzla Habib
    Hanzla Habib almost 4 years
    i have exactly same flow in my component, my other values when change compenent react to it but there is one property that is not triggering rerender even value is changed in redux store any thoughts around it?
  • zarathustra
    zarathustra over 2 years
    Thanks so much! This was the right answer for me!