Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-redux component does not rerender on store state change

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 ?

like image 701
Zalaboza Avatar asked Jul 30 '16 20:07

Zalaboza


People also ask

Does component Rerender on Redux state change?

React-redux component does not rerender on store state change.

Does React component Rerender when state changes?

React components automatically re-render whenever there is a change in their state or props. A simple update of the state, from anywhere in the code, causes all the User Interface (UI) elements to be re-rendered automatically.

Does Redux cause re-render?

Any time any piece of the Redux state is updated, our Component will re-render, regardless of whether the store update was related to our component or not.

How do you update a component in Redux state change?

The way you have it written, the state won't update unless you explicitly update it using setState() (most likely in the componentWillReceiveProps() method). When you use mapStateToProps() with the Redux connect() HOC, you are mapping your Redux state to your component through its props, so in your case this. props.


2 Answers

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

like image 50
Danny Avatar answered Oct 02 '22 15:10

Danny


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;
  }
}
like image 27
duhaime Avatar answered Oct 02 '22 14:10

duhaime