0

this is my reducer code

const authReducer = (
  state = {
    isAuthenticated: !AuthService.isTokenExpired(),
    isFetching: false,
    profile: AuthService.getProfile(),
    error: null
  },
  action
) => {

  switch (action.type) {    
   case types.LOGOUT_SUCCESS:
   return Object.assign({}, state, {
      isAuthenticated: false,
      isFetching: false,
      profile: {},
      error: null
    })
    default:
      return state;
  }

combinereducer.js

export default combineReducers({
    apiDataReducer,
    auth: authReducer
});

Main.js

  import rootReducer from './reducers/combineReducers';
    import reduxImmutableStateInvariant from 'redux-immutable-state-invariant';
    imp

ort thunk from 'redux-thunk';

const middleware = process.env.NODE_ENV !== 'production' ?  [reduxImmutableStateInvariant(), thunk] :  [thunk];

export let store = createStore(rootReducer, applyMiddleware(...middleware));

render(
  <Provider store={store}>
    <Router>
      <App />
    </Router>
  </Provider>,
  document.getElementById('root')
);

Header.js

  import React, { Component } from 'react';

    import { connect } from 'react-redux';
    import { withRouter } from 'react-router-dom';
    import * as authActions from '../../actions/basicActions';
    import HeaderView from './HeaderView';
    //import authReducer from './reducers/authReducer';


    const mapStateToProps = ({ auth }) => ({
      auth
      });

      const mapDispatchToProps = dispatch => ({
        loginRequest: () => dispatch(authActions.loginRequest()),
        logoutSuccess: () => dispatch(authActions.logoutSuccess())
      });

      export default withRouter(
        connect(mapStateToProps, mapDispatchToProps)(HeaderView)
      );

HeaderView.js

  handleLogoutClick = () => {
    this.props.logoutSuccess();
    this.props.history.push({ pathname: '/' });
  };

  render() {

    const { auth } = this.props;
    return (
      <div>
        {auth.isAuthenticated ? (
          <div>
            <div>
              <table>
                <tbody>

                      <label>
                        <aonClick={this.handleLogoutClick}> Log Out </a>
                      </label>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
            <nav className="navbar navbar-default">
              <ul className="nav navbar-nav">
                <li key="1" id="1" onClick={this.handleClick}><Link to={'/page2'}>page2</Link></li>
              </ul>
            </nav>
          </div>
        ) : (
            <label className="Note">
              logged in{' '} <a onClick={this.handleLoginClick}> Log In </a>
              {' '} to continue.
                </label>
          )}
      </div>
    );
  }

and this is my container component where state change in reducer auth is not reflecting SomeContainer.js

const mapStateToProps = ({ auth }) => ({
  auth
  });

  const mapDispatchToProps = dispatch => ({
  });

  export default connect(mapStateToProps, mapDispatchToProps)(SomeContainer);

When logout is clicked in HeaderView.js LOGOUTSUCCESS action gets called and reducer 'auth' changes value of 'isAuthenticated' in object but that change doesnt call 'mapStateToProps' function of connected Container, and value of reducer 'auth' is same i.e. true even after logout.

Shrikant Dande
  • 223
  • 1
  • 5
  • 17

1 Answers1

0

Because the child components do not re-render when a prop change occures from parent. You can think of connect HoC as the parent of HeaderView component. Check this question for more info on re-rendering conditions.

You need to change state using componentWillReceiveProps. In HeaderView.js file:

constructor(props) {
      super(props);
      this.state = {
         isAuthenticated = false
      }
}

componentWillReceiveProps(nextProps) {
     if(nextProps.auth.isAuthenticated !== this.props.auth.isAuthenticated) {
        this.setState({isAuthenticated: nextProps.auth.isAuthenticated});
     }
}

handleLogoutClick = () => {
    this.props.logoutSuccess();
    this.props.history.push({ pathname: '/' });
  };

render() {

    const { isAuthenticated } = this.state;
    return (
      <div>
        {isAuthenticated ? (
          <div>
            <div>
              <table>
                <tbody>

                      <label>
                        <aonClick={this.handleLogoutClick}> Log Out </a>
                      </label>
                    </td>
                  </tr>
                </tbody>
              </table>
            </div>
            <nav className="navbar navbar-default">
              <ul className="nav navbar-nav">
                <li key="1" id="1" onClick={this.handleClick}><Link to={'/page2'}>page2</Link></li>
              </ul>
            </nav>
          </div>
        ) : (
            <label className="Note">
              logged in{' '} <a onClick={this.handleLoginClick}> Log In </a>
              {' '} to continue.
                </label>
          )}
      </div>
    );
  }
  • Thanx, but actually I want updated value of isAuthenticated in 'SomeContainer.js' when I click on 'Log out' of 'HeaderView.js' in another tab. – Shrikant Dande Jun 21 '18 at 11:21
  • I think you can do the same thing (setting state) in SomeContainer.js. How do you use the `isAuthenticated` value in SomeContainer.js? – bircansinan Jun 21 '18 at 11:58
  • through Reducer i.e. `const mapStateToProps = ({ auth }) => ({ auth });` I check it like this `if (!this.props.auth.isAuthenticated) { this.props.history.push({ pathname: '/' }); }` – Shrikant Dande Jun 21 '18 at 12:01
  • `componentWillReceiveProps(nextProps) { if(nextProps.auth.isAuthenticated !== this.props.auth.isAuthenticated) { this.props.history.push({ pathname: '/' }); } }` I suppose this should work. – bircansinan Jun 21 '18 at 12:12
  • I tried this this function was not called. I think 'Connect' function also do the same, looks for change in state of redux store ,but don't know why it didnt ditect change here. – Shrikant Dande Jun 21 '18 at 12:26
  • other Connect containers are reflecting state change in reducer, only issue with 'HeaderView.js'. there is one diff between other connect containers and this is it has withRouter... maybe that is causing some issue. any way thanx a lot for help – Shrikant Dande Jun 21 '18 at 12:28