本文介绍了即使有依赖关系,useEffect 也会无限地分派动作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
在 useEffect
中使用 dispatch 时,我有一个无限的 dispatch.
import React, { useEffect } from "react";从./TodoItem"导入 TodoItemimport { useDispatch, useSelector } from react-redux";import { getTodos } from "../redux/actions";const TodoList = () =>{const dispatch = useDispatch()useEffect(() => {调度(getTodos())}, [getTodos])const todos = useSelector(state => state)返回 (<div style={{ width: "75%", margin: "auto";}}><h3>待办事项列表</h3>{console.log(挂载")}{todos &&todos.map(todo => {return })}{todos &&!todos.length &&<h3>没有任务要做.添加一个!</h3>}
)}导出默认 TodoList
sagas.js:
import { call, put, takeEvery } from "redux-saga/effects";const apiUrl = "https://jsonplaceholder.cypress.io/todos";函数 getApi() {返回获取(apiUrl,{方法:GET",标题:{内容类型":应用程序/json";}}).then(response => response.json()).catch(错误=> {抛出错误})}函数* fetchTodos(动作){尝试 {const todos = yield call(getApi)const todosList = todos.slice(0, 20)yield put({ type: "GET_TODOS", todosList })} 捕捉(错误){console.log({ 错误 })}}函数* todoSagas() {yield takeEvery(GET_TODOS", fetchTodos)}导出默认 todoSagas
解决方案
saga 本身正在创建一个无限循环,因为您使用相同的操作名称GET_TODOS"来启动提取和存储提取的结果.您从 fetchTodos
中put
的操作将被您的 takeEvery
再次接收.
您需要两种不同的操作类型,例如REQUEST_TODOS"和RECEIVE_TODOS".请求操作没有有效负载,而成功操作有一个有效负载,其中包含来自您的 fetch 的待办事项数组.您的减速器会忽略请求操作(除非您想使用它来设置像 loading: true
这样的属性).对于成功操作,您的减速器将存储从有效负载属性中获取的结果.
I'm having an infinite dispatch when using dispatch within useEffect
.
import React, { useEffect } from "react"
import TodoItem from "./TodoItem"
import { useDispatch, useSelector } from "react-redux"
import { getTodos } from "../redux/actions"
const TodoList = () => {
const dispatch = useDispatch()
useEffect(() => {
dispatch(getTodos())
}, [getTodos])
const todos = useSelector(state => state)
return (
<div style={{ width: "75%", margin: "auto" }}>
<h3>Todo List</h3>
{console.log("mounted")}
{todos &&
todos.map(todo => {
return <TodoItem key={todo.id} title={todo.title} id={todo.id} />
})}
{todos && !todos.length && <h3>There are no tasks to do. Add one!</h3>}
</div>
)
}
export default TodoList
sagas.js:
import { call, put, takeEvery } from "redux-saga/effects"
const apiUrl = "https://jsonplaceholder.cypress.io/todos"
function getApi() {
return fetch(apiUrl, {
method: "GET",
headers: {
"Content-Type": "application/json"
}
})
.then(response => response.json())
.catch(error => {
throw error
})
}
function* fetchTodos(action) {
try {
const todos = yield call(getApi)
const todosList = todos.slice(0, 20)
yield put({ type: "GET_TODOS", todosList })
} catch (error) {
console.log({ error })
}
}
function* todoSagas() {
yield takeEvery("GET_TODOS", fetchTodos)
}
export default todoSagas
解决方案
The saga itself is creating an infinite loop because you use the same action name "GET_TODOS" for both initiating the fetch and storing the results of the fetch. The action that you put
from fetchTodos
will be picked up again by your takeEvery
.
You want two separate action types, for example "REQUEST_TODOS" and "RECEIVE_TODOS". The request action has no payload, while the success action has a payload with the array of todos from your fetch. Your reducer would ignore the request action (unless you want to use it to set a property like loading: true
). For the success action, your reducer will store the results of your fetch from the payload property.
这篇关于即使有依赖关系,useEffect 也会无限地分派动作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!