0

I am new to redux and trying to create a small site in which users can: login, register and logout.

I have created 2 reducers for login and registration and I have a "isLoggedIn" field initialized in both reducers' state.

When trying to create a 3rd reducer for logout, adding it to the CombineReducers and then try to login/register, it is not logging me out, it does nothing. The only thing that is working is if I am using only the login and register reducers, and on each reducer I add a 'case LOGOUT'.

However, I feel like there is a better way of doing that since it is duplicating my code on all reducers that needs the logout functionality.

authentication.js (login)

import { userConstants } from "../constants";

const initialState = {
  user: {
    email: "",
    username: "",
  },
  isLoggedIn: false,
};

export function authentication(state = initialState, action) {
  switch (action.type) {
    case userConstants.LOGIN_REQUEST:
      return Object.assign({}, state, {
        isLoggedIn: false,
      });
    case userConstants.LOGIN_SUCCESS:
      return Object.assign({}, state, {
        isLoggedIn: true,
        user: action.user,
      });
    case userConstants.LOGIN_FAILURE:
      return {};
    case userConstants.LOGOUT:
      return Object.assign({}, state, {
        isLoggedIn: false,
      });
    default:
      return state;
  }
}

registration.js

import { userConstants } from "../constants";

export function registration(state = { isLoggedIn: false, user: {} }, action) {
  switch (action.type) {
    case userConstants.SIGN_UP_REQUEST:
      return Object.assign({}, state, {
        isLoggedIn: false,
      });
    case userConstants.SIGN_UP:
      return Object.assign({}, state, {
        isLoggedIn: true,
        user: action.user,
      });
    case userConstants.SIGN_UP_FAILED:
      return {};
    case userConstants.LOGOUT:
      return Object.assign({}, state, {
        isLoggedIn: false,
      });
    default:
      return state;
  }
}

reducers/index.js

import { combineReducers } from "redux";

import { authentication } from "./authentication";
import { registration } from "./registration";

const rootReducer = combineReducers({
  authentication,
  registration,
});

export default rootReducer;

routes/index.js

function mapStateToProps(state) {
  return {
    isLoggedIn:
      state.authentication.isLoggedIn || state.registration.isLoggedIn,
  };
}

const mapDispatchToProps = (dispatch) => ({
  logout: () => dispatch(logout()),
});

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

store.js

import { createStore, applyMiddleware, compose } from "redux";
import rootReducer from "./reducers";
import thunk from "redux-thunk";
import { createLogger } from "redux-logger";

const logger = createLogger();

const store = createStore(
  rootReducer,
  compose(applyMiddleware(thunk), applyMiddleware(logger))
);

export default store;

In routes/index.js I am using the "isLoggedIn" field in order to show the user specific pages depends on if he is logged in or not.

The above program is the only solution I was able to achieve.

Also, if it matters, all my actions for logout, login and register are within the same file.

isherwood
  • 58,414
  • 16
  • 114
  • 157
Wicked528
  • 1
  • 1
  • 1
  • What is inside userConstants? – ChrisR May 18 '20 at 13:24
  • I have an object of userConstants with: SIGN_UP, SIGN_UP_REQUEST, LOGIN_SUCCESS, etc and each one of them is a string with the same value as the name for instance: SIGN_UP = "SIGN_UP" – Wicked528 May 18 '20 at 13:37

1 Answers1

0

I eventually put the register and login reducers within the file - same reducer, all the switch/cases were put together, since they are both in need of using the "isLoggedIn" field.

I guess this is a good solution for me now since they both need to use the same state from reducer, but it probably won't work as well if register and login would have different logic.

Wicked528
  • 1
  • 1
  • 1