Реагировать на обновленный контекст, недоступный с помощью AOC HOC - PullRequest
0 голосов
/ 25 апреля 2020

Я работаю над аутентификацией для реактивного проекта, используя useContext, useReducer и компонент высшего порядка (HO C) для аутентификации маршрутов.

Проблема, с которой я сталкиваюсь, заключается в том, что после входа в систему, HO C перенаправляет на страницу входа в систему, потому что unAuthenticated возвращает значение false, даже если для него установлено значение true, непосредственно перед тем, как оно достигнет HO C.

withAuth HO C Я использую для проверки, аутентифицирован ли пользователь и разрешен ли доступ к определенным маршрутам

import React from 'react';
import { Redirect } from 'react-router-dom';
import { verifyRole } from '../../helpers/auth.helpers';
import withUser from '../WithUser';

const withAuth = (...permittedRoles) => (ComposedComponent) => {
  const Authorization = (props) => {

    const { isAuthenticated } = props;

    if (!isAuthenticated) return <Redirect to='/signin' />;

    if (!verifyRole(...permittedRoles)) {
      return <Redirect to='/' />;
    }
    return <ComposedComponent {...props} permittedRoles={permittedRoles} />;
  };
  return withUser(Authorization);
};

export default withAuth;

withUser HO C, который обеспечивает состояние контекста для использования

import React from 'react';
import { UserContext } from '../../context/userContext';

const withUser = (ComposedComponent) => (props) => (
  <UserContext.Consumer>
    {(user) => <ComposedComponent {...props} {...user} />}
  </UserContext.Consumer>
);
export default withUser;

authReducer Редуктор, который я использую для обновления контекста

import {
  SIGNIN_START,
  SIGNIN_FAILURE,
  SIGNIN_SUCCESS,
} from '../actions/actionTypes';

const authReducer = (state, action) => {
  switch (action.type) {
  case SIGNIN_START:
    return { ...state, isLoading: true, isAuthenticated: false, errorMsg: null };
  case SIGNIN_SUCCESS:
    return {
      ...state,
      isLoading: false,
      response: action.payload,
      errorMsg: null,
      isAuthenticated: true,
    };
  case SIGNIN_FAILURE:
    return {
      ...state,
      isLoading: false,
      response: action.payload.response,
      errorMsg: action.payload.response
        ? action.payload.response.data.message
        : 'Sorry, there was an error, please try again',
      isAuthenticated: false,
    };
  default:
    return state;
  }
};

export default authReducer;

actions Auth actions

import { SIGNIN_START, SIGNIN_FAILURE, SIGNIN_SUCCESS } from './actionTypes';

const signinStart = () => ({
  type: SIGNIN_START,
});

const signinSuccess = (payload) => ({
  type: SIGNIN_SUCCESS,
  payload,
});

const signinFailure = (payload) => ({
  type: SIGNIN_FAILURE,
  payload,
});

export const signin = (dispatch) => {
  dispatch(signinSuccess())
}
const signinUser = async (dispatch, userObject) => {
  dispatch(signinStart());
  try {
    const user = await Axios.post(`${process.env.REACT_APP_BASE_API_URL}/auth/signin`, {
      ...userObject,
    });

    if (user) {
      const { token } = user.data;
      localStorage.setItem('token', token);
      dispatch(signinSuccess(token));
      return true;
    }
  } catch (error) {
    dispatch(signinFailure(error));
  }
};

export default signinUser;

SigninComponent

import React, { useState, useContext } from 'react';
import swal from 'sweetalert';
import ClipLoader from 'react-spinners/ClipLoader';

import FormStyles from '../../styles/FormStyles.module.scss';
import SigninStyles from './Signin.module.scss';
import { UserContext } from '../../context/userContext';
import signinUser from '../../actions/auth.action';

export const Signin = ({history}) => {
  const initialState = {
    username: '',
    password: '',
  };

  const [signinState, setSigninState] = useState(initialState);

  const { dispatch, errorMsg, isLoading } = useContext(UserContext);
  const { username, password } = signinState;

  const handleInputChange = (event) => {
    setSigninState({
      ...signinState,
      [event.target.name]: event.target.value,
    });
  };

  const handleSignin = (e) => {
    e.preventDefault();
    const signinResult = signinUser(dispatch, { username, password });
    if(signinResult)  history.push('/');

    if(errorMsg) {
      swal('Oops!!!', errorMsg, 'error');
    }
  };

  return (
    <div className={SigninStyles.formContainer}>
      <h2 className={`${FormStyles['form-title']} container`}>Signin</h2>
      <form className={SigninStyles.formBody} onSubmit={handleSignin}>
        <p className={FormStyles['input-group']}>
          <label htmlFor='username'>Username</label>
          <input
            type='text'
            name='username'
            id='username'
            placeholder='Username'
            onChange={handleInputChange}
            value={username}
            required
          />
        </p>
        <p className={FormStyles['input-group']}>
          <label htmlFor='password'>Password</label>
          <input
            type='password'
            name='password'
            id='password'
            placeholder='password'
            onChange={handleInputChange}
            value={password}
            required
          />
        </p>
        <p className={FormStyles['btn-group']}>
          <button
            className={`${FormStyles['btn']} ${FormStyles['btn-maroon']}`}
          >
            {!isLoading && 'Add user'}
            <ClipLoader loading={isLoading} size='30px' color='#fff' />
          </button>
          <a href='/forgot-password' className={FormStyles['forgot-password']}>
            Forgot password?
          </a>
        </p>
      </form>
    </div>
  );
};

export default Signin;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...