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$)]);
}
这应该可以解决您的问题。
我使用 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$)]);
}
这应该可以解决您的问题。