首页 > 解决方案 > 即使有依赖关系,useEffect 也会无限地调度一个动作

问题描述

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


在此处查看日志

标签: javascriptreactjsreduxredux-saga

解决方案


saga 本身正在创建一个无限循环,因为您使用相同的操作名称“GET_TODOS”来启动提取和存储提取结果。put您的操作fetchTodos将再次被您的takeEvery.

您需要两种不同的操作类型,例如“REQUEST_TODOS”和“RECEIVE_TODOS”。请求操作没有有效负载,而成功操作有一个有效负载,其中包含来自您获取的待办事项数组。您的减速器会忽略请求操作(除非您想使用它来设置类似 的属性loading: true)。对于成功操作,您的减速器将存储您从有效负载属性中获取的结果。


推荐阅读