Redux saga 进入调用 api 端点的无限循环状态

Redux saga enters in infinite loop state of calling api endpoint

我使用 Redux 进行状态管理,使用 saga 作为中间件。出于某种原因,我的应用程序处于调用 API 端点的某种无限循环状态。

这是我的操作:

export const GET_USERS = "GET_USERS";
export const getUsers = () => ({
  type: GET_USERS,
});

export const GET_USERS_SUCCESS = `${GET_USERS}_SUCCESS`;
export const getUsersSuccess = (data) => ({
  type: GET_USERS_SUCCESS,
  payload: data,
});

export const GET_USERS_FAIL = `${GET_USERS}_FAIL`;
export const getUsersFail = (error) => ({
  type: GET_USERS_FAIL,
  payload: error,
});

这是传奇:

export function* getUsers$() {
  try {
    const users = yield getUsersAPI();
    yield put(actions.getUsersSuccess(users.data));
  } catch (error) {
    yield put(actions.getUsersFail(error));
  }
}

export default function* () {
  yield all([takeLatest(actions.getUsers, getUsers$)]);
}

这是一个减速器:

export default (state = initialState(), action) => {

  const { type, payload } = action;

  switch (type) {
    case actions.GET_USERS:
      return {
        ...state,
        users: {
          ...state.users,
          inProgress: true,
        },
      };
    case actions.GET_USERS_SUCCESS:
      return {
        ...state,
        users: {
          inProgress: false,
          data: payload,
        },
      };
    case actions.GET_USERS_FAIL:
      return {
        ...state,
        users: {
          ...state.users,
          inProgress: false,
          error: payload,
        },
      };
    default:
      return state;
  }
};

这是一个与redux连接的组件:

const Home = (props) => {

    useEffect(() => {
        props.getUsers();
        console.log('props', props.data);
    }, []);
   return(
    <h1>Title</h1>
   );
}

const mapStateToProps = ({
    users: {
        users: {
            data
        }
    }
}) => ({data})


export default connect(mapStateToProps, {getUsers})(Home);

为什么会这样?

这是因为您在示例中误用了 sagas。与任何其他 effect creator 一样,第一个参数必须传递一个 pattern,可以在文档中阅读更多详细信息。第一个参数也可以传递 function,但方式略有不同。查看 documentation(块 take(pattern))。

在你的例子中,你正在传递一个函数,它将return一个对象

{
  type: 'SOME_TYPE',
  payload: 'some_payload',
}

因此,您的 worker 将对您 dispatch 所有 事件作出反应。 结果,您从服务器接收数据,dispatch 一个新的 action 来保存来自存储的数据。除了 reducer,你的 getUsers saga 也将被调用来执行此操作。以此类推。

解决方案

要解决此问题,只需使用您在操作中定义的字符串常量 actions.GET_USERS。 您的 sagas 将如下所示:

export function* getUsers$() {
  try {
    const users = yield getUsersAPI();
    yield put(actions.getUsersSuccess(users.data));
  } catch (error) {
    yield put(actions.getUsersFail(error));
  }
}

export default function* () {
  yield all([takeLatest(actions.GET_USERS, getUsers$)]);
}

这应该可以解决您的问题。