Redux-saga get data from action returns patternOrChannel is undefined
Asked Answered
M

3

5

I need to send dynamic data from my screen to action/reducer and fetch data from API with that data, but when i yield in my rootSaga i'll get an error like this:

uncaught at check take(patternOrChannel): patternOrChannel is undefined
uncaught at rootSaga at rootSaga
at takeEvery
Error: take(patternOrChannel): patternOrChannel is undefined

Screen code:

import { checkUserLoginStatus, userSignin } from '../actions/user';

class PreCheckout extends PureComponent {
   handleLogin = () => {
     this.props.dispatch(userSignin(username, password));
   };
   render() { .......

Action:

const USER_SIGNIN = 'USER_SIGNIN';

export const userSignin = (username, password) => ({
   type: USER_SIGNIN,
   username,
   password,
});

Reducer:

import {
  CHECK_USER_LOGIN_STATUS,
  USER_SIGNIN,
  USER_SIGNIN_RESULT,
  USER_SIGNIN_ERROR,
} from '../actions/user';

const initialState = {
  isLoggedIn: false,
  isFetching: false,
  information: {},
  error: null,
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case CHECK_USER_LOGIN_STATUS:
      return {
        ...state,
      };
    case USER_SIGNIN:
      return {
        ...state,
        isFetching: true,
      };
    case USER_SIGNIN_RESULT:
      return {
        ...state,
        isFetching: false,
        information: action.result,
      };
    case USER_SIGNIN_ERROR:
      return {
        ...state,
        isFetching: false,
        error: action.error,
      };

Redux-Saga:

import {
  USER_SIGNIN,
  USER_SIGNIN_RESULT,
  USER_SIGNIN_ERROR,
} from '../actions/user';

function* fetchUserInformation(action) {
  try {
    console.log('fetchUserInformation action: ', action);
    const response = yield call(login, action);
    yield put({
      type: USER_SIGNIN_RESULT,
      result: response.result,
    });
  } catch (e) {
    yield put({
      type: USER_SIGNIN_ERROR,
      error: e.message,
    });
  }
}

export default function* rootSaga() {
  yield takeEvery(USER_SIGNIN, fetchUserInformation);
}
Micturition answered 22/1, 2018 at 9:45 Comment(7)
looks pretty much like some of your constants are undefined, make sure that all of them are definedGuaranty
I cannot find any undefined there.Micturition
could you please add the imports in actions / saga / reducer ?Guaranty
@JoseAPL I've updated my question with the imports.Micturition
You forgot to export constant **export** const USER_SIGNIN = 'USER_SIGNIN'; or somewhere below export { USER_SIGNIN };Guardsman
@YuryTarabanko Oops!!!! such a big mistake!! Thank you!Micturition
@YuryTarabanko If you post an answer i'll mark it as correct answer.Micturition
G
9

As I have mention in comment. You simply forgot to export the constant.

Should be

export const USER_SIGNIN = 'USER_SIGNIN';

Or

const USER_SIGNIN = 'USER_SIGNIN';

...

export { USER_SIGNIN };

These types of bugs could be captured by eslint using eslint-plugin-import with this rule enabled.

Guardsman answered 22/1, 2018 at 10:52 Comment(0)
E
3

Probably USER_SIGNIN is undefined.

Elytron answered 22/1, 2018 at 9:51 Comment(5)
No, USER_SIGNIN imported correctly. btw, do you think this way is correct?Micturition
@MortezaAghili I would use takeLatest insteadGuaranty
@JoseAPL Can you tell me how? and why? Thanks.Micturition
@MortezaAghili imagine you have an auto-complete input which requests to an API every time the user changes the input, takeLatest will take the latest and kill the old onesGuaranty
@JoseAPL Aha, you introduce takeLatest with an awesome example. Thank you.Micturition
L
0

Just in case someone is using TypeScript: when defining the reducer actions as an enum, make sure to replace the default value of each enum item to a string, e.g:

// It will fail when using `Action.USER_SIGNIN` 
// because it's implicitly being set as the enum item position index (a number).
enum Action {
  USER_SIGNIN
}

// You need to define as string value instead:
enum Action {
  USER_SIGNIN = 'USER_SIGNIN'
}
Lankford answered 21/4, 2023 at 6:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.