对于一个学校项目,我的团队正在构建一个表,该表通过数据库调用填充了城市数据。
table-component的框架如下:

import React, { useState } from 'react'

function Table(props) {
  const [ cities, setCities ] = useState([])
  const [ pageNum, setPageNum ] = useState(0)

  useEffect(()=> { // this sets up the listener for the infinite scroll
    document.querySelector(".TableComponent").onscroll = () => {
      if (Math.ceil(table.scrollHeight - table.scrollTop) === table.clientHeight) showMoreRows()
    }
    //initial fetch
    fetchData(0)
  },[])

  async function showMoreRows() {
    console.log("Show more rows!")
    await fetchData(pageNum)
  }

  async function fetchData(page) {
    // some code, describing fetching
    // EDIT2 start
    console.log(pageNum)
    // EDIT2 end
    const jsonResponse = await {}// THE RESPONSE FROM THE FETCH
    if(page) {
      setCities([...cities, ...jsonResponse])
      console.log("page is true", page)
      setPageNum(pageNum + 1)
    } else {
      console.log("page is false", page) // this always runs and prints "page is false 0"
      setCities([...cities, ...jsonResponse])
      setPageNum(1)
    }
  }


  return <div className="TableComponent"> { pageNum }
           <!-- The rest of the component -->
         </div>
}


该表具有“无限滚动”功能,因此,当您滚动到页面底部时,它将打印"Show more rows!"并运行fetchData(pageNum)以获取更多数据。此时,在初始获取之后,pageNum变量应为1或更大,但是由于某种原因,该函数的作用好像是0。我将pageNum变量显示在JSX中,然后可以看到它是1,但是当我运行它时,它仍然会打印出"page is false 0"

当我尝试通过Google搜索问题时,似乎唯一相似的事情可能是我尝试在使用setPageNum之后(重绘之前)过早读取useState-variable,但是据我所知,这里并非如此。我会在两次尝试之间留出足够的时间,并且总是说pageNum为零。

关于我在做什么错的任何想法,以及这在任何方面如何有意义?

谢谢你的帮助!

编辑:刚刚尝试了我写的代码,它似乎可以工作-但是我拥有的完整代码不起作用。即使上面的代码可行,对这个问题有任何想法吗?

EDIT2:我在console.log(pageNum)函数中添加了fetchData,并进行了一些测试,看来我在useState(VALUE)初始值中输入的内容都是正在打印的内容。这对我来说毫无意义。
帮帮我。

EDIT3:添加了等待,已经在真实代码中

EDIT4:我已经尝试了一段时间,但意识到当我使用react时,我可以将滚动侦听器移至JSX区域,然后由于某些原因而起作用。现在可以使用了。不能真正将任何答案标记为正确的答案,但问题已得到解决。

感谢所有尝试提供帮助的人,非常感谢。

最佳答案

由于React不了解您对组件状态的依赖性,因此发生了陈旧性问题。

例如,useEffect确保在每次滚动时都会调用初始渲染范围内的showMoreRows值。 showMoreRows的此副本引用pageNum的初始值,但是该值在closure中与函数一起被“冻结”,并且在组件状态改变时不会更改。因此,滚动侦听将无法工作,因为它需要知道pageNum的当前状态。

您可以通过使用callbacks“ hookify” showMoreRowsfetchData并声明它们对组件状态的依赖性来解决问题。然后,您必须声明useEffect对这些回调的依赖性,并使用clean-up function处理多次被调用的效果。

看起来像这样(我没有尝试运行代码):

import React, { useState } from 'react'

function Table(props) {
  const [ cities, setCities ] = useState([])
  const [ pageNum, setPageNum ] = useState(0)

  useEffect(()=> {
    // Run this only once by not declaring any dependencies
    fetchData(0)
  }, [])

  useEffect(()=> {
    // This will run whenever showMoreRows changes.

    const onScroll = () => {
      if (Math.ceil(table.scrollHeight - table.scrollTop) === table.clientHeight) showMoreRows()
    };

    document.querySelector(".TableComponent").onscroll = onScroll;

    // Clean-up
    return () => document.querySelector(".TableComponent").onscroll = null;
  }, [showMoreRows])

  const showMoreRows = React.useCallback(async function () {
    console.log("Show more rows!")
    await fetchData(pageNum)
  }, [fetchData, pageNum]);

  const fetchData = React.useCallback(async function (page) {
    // some code, describing fetching
    // EDIT2 start
    console.log(pageNum)
    // EDIT2 end
    const jsonResponse = await {}// THE RESPONSE FROM THE FETCH
    if(page) {
      setCities([...cities, ...jsonResponse])
      console.log("page is true", page)
      setPageNum(pageNum + 1)
    } else {
      console.log("page is false", page) // this always runs and prints "page is false 0"
      setCities([...cities, ...jsonResponse])
      setPageNum(1)
     }
  }, [setCities, cities, setPageNum, pageNum]);

  return <div className="TableComponent"> { pageNum }
           <!-- The rest of the component -->
         </div>
}

关于javascript - 为什么我的函数无法读取组件状态的实际值?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58440954/

10-13 04:59