Изменение состояния в redux-saga приводит к бесконечному циклу внутри компонента

#javascript #reactjs #redux #react-router #redux-saga

Вопрос:

Я пытаюсь перенаправить пользователя после успешного входа в систему, но изменение состояния в saga вызывает бесконечный цикл.

компонент

В моем компоненте я использую useSelector для прослушивания изменений в сеансе isValidSession из магазина. Если сеанс isValidSession изменится на true, я хочу перенаправить пользователя на другую страницу. Однако при изменении сеанса isValidSession мой компонент продолжает выполнять рендеринг в бесконечном цикле.

 import { Link, useLocation } from 'react-router-dom' import { Redirect } from 'react-router'  import MainLayout from '../../../layouts/MainLayout' import { Typography, Alert, Row, Col, Divider } from 'antd' import LoginForm from './LoginForm'  import { useDispatch, useSelector } from 'react-redux' import * as loginActions from './Login.action'  const { Title } = Typography  export default function Login() {   const dispatch = useDispatch()   const { isValidSession, error } = useSelector((state) =gt; state.login)   const location = useLocation()   let { from } = location.state || { from: { pathname: '/templates' } }   const handleLogin = ({ email, password }) =gt;  {  dispatch(loginActions.authenticate({ email, password }))  }   const getAPIError = (error) =gt;  error.status == 401  ? 'Invalid username or password'  : 'Something went wrong'   if (isValidSession) return lt;Redirect push to={from.pathname} /gt;   return (  lt;MainLayoutgt;  lt;Row align='stretch' className='vh-100'gt;  lt;Col xs={24} md={12} lg={10} xl={8} xxl={6} className='bg--white'gt;  lt;div className='d-flex align-items-center h-100 p-5'gt;  lt;div id='login' className='w-100'gt;    lt;Title level={3}gt;Welcome Back!lt;/Titlegt;   {/* ERROR MESSAGE */}  {error ? (  lt;Alert  message={getAPIError(error)}  showIcon  type='error'  className='mb-2'  /gt;  ) : (  ''  )}   {/* FORM */}  lt;LoginForm onFinish={handleLogin} /gt;   lt;Divider /gt;   {/* ADDITIONAL LINKS */}  lt;div className='text-center'gt;  lt;pgt;  Don't have an account yet?{' '}  lt;Link  to={{ pathname: '/register', state: { from: location } }}  gt;  Sign up  lt;/Linkgt;  lt;/pgt;  lt;Link  to={{  pathname: '/auth/recover-password',  state: { from: location },  }}  gt;  Forgot your password?  lt;/Linkgt;  lt;/divgt;  lt;/divgt;  lt;/divgt;  lt;/Colgt;  lt;/Rowgt;  lt;/MainLayoutgt;  ) }  

редуктор

В моем редукторе, для типов действий.LOGIN_SUCCESS, я делаю сеанс isValidSession равным true.

 const loginReducer = (state = initialState, action) =gt; {  switch (action.type) {  case types.LOGIN_REQUESTING: {  return {  ...state,  submitted: false,  }  }  case types.LOGIN_SUCCESS: {  return {  ...state,  submitted: true,  successful: true,  isValidSession: true,  }  }  case types.LOGIN_ERROR: {  const { error } = action  return {  ...state,  error,  submitted: false,  successful: false,  isValidSession: false,  }  }  case types.UPDATE_LOGIN_CREDENTIAL: {  const { login } = action  return {  ...state,  login: {  ...state.login,  ...login,  },  }  }  case types.IS_LOGGINGIN: {  const { isLoggingIn } = action  return {  ...state,  isLoggingIn,  }  }  default:  return {  ...state,  }  } }    

saga

In my saga code, you can see that I am doing yield put({ type: types.LOGIN_SUCCESS }) to change isValidSession to true.

 function* authenticateSage(payload) {  try {  alert('authenticateSage')   const response = yield call(authService.login, payload.login)  const { profile, account } = response   yield put({ type: types.LOGIN_SUCCESS })  } catch (error) {  yield put({  type: types.LOGIN_ERROR,  error: { status: error.status, message: error.data?.message },  })  } }  export default function* watchAuthentication() {  yield takeLatest(types.LOGIN_REQUESTING, authenticateSage) }