【问题标题】:Can't map array with useEffect and React Redux无法使用 useEffect 和 React Redux 映射数组
【发布时间】:2020-11-15 05:35:02
【问题描述】:

在 useEffect 获取数组并将其分派到我的 redux 状态后,我正在尝试映射员工列表。如果我控制台记录它,我会看到一个充满对象的数组,但我的组件似乎没有重新渲染。有什么建议吗?

import React, { useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { setEmployees } from '../redux/reducers/employeeListReducer'
import employeesService  from '../back-end/services/employees'

const EmployeeList = ({  }) => {
  const dispatch = useDispatch()
  const employees = useSelector(state => state.employeeList) 
  const user = useSelector(state => state.user)

  employeesService.setToken(user.token)

  useEffect(() => {
    (async () => {
    const employeeList = await employeesService.getAll()
         dispatch(setEmployees(employeeList))
     })();
  
  }, [dispatch])
  
  if (employees === null) {
    return <p>Loading Employees...</p>
  }
  return (
    <div>
      {console.log(employees)}
       {employees.map(e =>
        <div key={e.id}>
          {e.name} {e.phone} {e.email}
        </div>  
      )} 
    </div>
  )
}

export default EmployeeList

【问题讨论】:

  • 我修好了,根本问题出在减速器上。我将 return [action.data] 更改为 return action.data,现在它可以正常工作了。我读了一篇关于在 reducer 中改变状态防止组件重新渲染的文章。

标签: reactjs react-redux use-effect


【解决方案1】:

从描述中不清楚可能导致您描述的第一个问题的原因(没有console.log 我们可以查看以确定为什么存在差异),但是您不能从提供给其他钩子的回调中调用钩子.这是挂钩如何实现的限制。它们依赖于总是以相同的顺序被调用(所以你不能有条件地调用钩子函数),并且它们必须在你的函数返回时都被调用。详细信息可以在这里找到:

https://reactjs.org/warnings/invalid-hook-call-warning.html

基本上,您必须在功能组件的顶层或另一个挂钩的顶层调用挂钩函数(例如,您会看到使用其他挂钩实现的挂钩)。在您的函数返回时,必须调用所有钩子函数。如果在回调中调用钩子,它很可能会在您的函数返回后 被调用。所以 React 会警告你。

综上所述,将 dispatch 的声明移至组件的顶层应该可以解决此问题:

import React, {useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { setEmployees} from '../redux/reducers/employeeListReducer'
import employeesService  from '../back-end/services/employees'


const EmployeeList = ({ employee }) => {
  const dispatch = useDispatch()
  const employees = useSelector(state => state.employeeList) 
  const user = useSelector(state => state.user)
  employeesService.setToken(user.token)

  useEffect(() => {
    employeesService
      .getAll()
      .then(employeeList => {
         dispatch(setEmployees(employeeList))
      })
  }, [dispatch])

  return (
    <div>
      Employee List Placeholder
       {employees.map(e =>
        <div key={e.id}>
          {e.name} {e.phone} {e.email}
        </div>  
      )} 
    </div>
  )
}

export default EmployeeList

【讨论】:

  • 我已经编辑了我的帖子,console.log 显示了员工数组,其中包含一组对象。但是我的组件似乎没有重新渲染,因为数组没有映射到显示所有员工。因此,对于第二个问题,如果我将调度移至顶级函数,则会收到此错误“React Hook useEffect has a missing dependency:'dispatch'。要么包含它,要么移除依赖数组 react-hooks/exhaustive-deps'
  • 啊,我的错,useEffect hook 需要 dispatch 作为依赖传入。我更新了我的答案。看看这是否解决了这两个问题。你有你的 console.log 意味着你的元素应该匹配它。
  • 谢谢,丢失的依赖错误已修复,请参阅我对代码的最新编辑。看来我仍然无法映射我的员工数组。我想如果我在 useEffect 中使用异步函数可能会有所帮助,但我有同样的问题。正如您在图像中看到的那样,Redux 状态确实会正确更新。员工数组更新了几个员工对象,请参见 console.log 图像,但我的组件仍然没有映射到它。如果我硬编码一个对象数组,它映射得很好,我会很困惑,因为我理解状态变化应该触发组件重新渲染。还有其他想法吗?
  • 我添加了一个 if 语句,以便在员工 === null 时给出加载消息。我可以看到加载消息,但是一旦使用employeeService.getAll() 获取数据并且使用新数组更新员工状态,加载消息就会消失,但仍然没有映射数组。这对我来说更令人费解。
猜你喜欢
  • 2017-06-01
  • 1970-01-01
  • 2019-12-03
  • 2018-02-24
  • 2019-04-28
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
  • 1970-01-01
相关资源
最近更新 更多