React Hook:重新渲染列表项导致无限循环

时间:2020-07-28 14:33:39

标签: reactjs react-hooks rendering

我创建了一个用户列表(运行良好),对于某些用户,我需要调用新的异步函数(fetch)来更新数据。但这会导致无限循环。

这是我的代码:

function UserTableRow(props) {
 const [pointOfSales, updatePointOfSales] = useState([])


  function Pos({ id }) {

  useEffect(() => {
  let mounted = true

    pointOfSaleService.getById(id).then((pointOfSale: PointOfSale) => {
      if (mounted && !pointOfSales.includes(pointOfSale)) {
        updatePointOfSales([...pointOfSales, pointOfSale]) <---- loop here
      }
    })
    return function cleanup() {
      mounted = false
    }
  }, [])

  if (pos) {
    return <Typography variant="body2">{pointOfSales[pointOfSales.length-1].name}</Typography>
  } else {
    return <span />
  }
}

return (
  <TableRow>
    <UserTableCell component="th" scope="row">
      {user.name}
    </UserTableCell>
   ...
    <UserTableCell align="left">
      {user.posId > 0 && <Pos id={user.posId} />}
    </UserTableCell>
  </TableRow>
)

}

我测试过的东西:

  • 如果我将pos或pointOfSales作为useEffect的依赖项,我得到的结果相同
  • 如果我不使用useEffet,请直接使用pointOfSaleService.getById(id)

我不了解两个主要问题。

  • 数组填充良好,但是为什么这行!pointOfSales.includes(pointOfSale)不起作用?
  • 为什么方法pointOfSaleService.getById(id)总是检索相同的pointOfSale,但为什么要使用“ updatePointOfSales”更新pointOfSales?

请帮助我

1 个答案:

答案 0 :(得分:0)

尝试简化您的代码。我认为Pos是一个表示性的组件,不应执行任何请求(应在UserTableRow中进行)。

function UserTableRow({ user }) {
 const [pointOfSales, updatePointOfSales] = useState([])

 useEffect(() => {
   let mounted = true

    pointOfSaleService.getById(user.posId).then(pointOfSale => {
      // I assume pointOfSale is a string
      // if it does, consider changing pointOfSales to string instead of Array
      if (mounted && !pointOfSales.includes(pointOfSale)) {
        updatePointOfSales([...pointOfSales, pointOfSale])
      }
    })
    return function cleanup() {
      mounted = false
    }
 }, [user.posId])

 return (
      <TableRow>
        <UserTableCell component="th" scope="row">
         {user.name}
        </UserTableCell>
        ...
        <UserTableCell align="left">
         {
           pointOfSales.length > 0 
           ? <Typography variant="body2">{pointOfSales[pointOfSales.length-1].name}</Typography> 
           : <span/> 
         }
        </UserTableCell>
     </TableRow>
 )

}

关于您已实现的方法的最后一件事是它的执行情况确实很差。具有50个用户的图像,当呈现其相应的行时,您将向服务器发出50个请求(检索用户时,我宁愿包含pointOfSale。)