本文介绍了即使有依赖关系,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"来启动提取和存储提取的结果.您从 fetchTodosput 的操作将被您的 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 也会无限地分派动作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 17:37