为什么反应功能组件中的回调没有读取更新的状态值

戈帕尔·夏尔马

我试图在反应中使用交叉点观察器实现无限滚动,但我面临的问题是在交叉点观察器的回调中,我无法读取当前“页面”和“列表”的最新值,以便我可以获取数据下一页。

import ReactDOM from "react-dom";
import "./styles.css";
require("intersection-observer");

const pageSize = 30;
const threshold = 5;

const generateList = (page, size) => {
  let arr = [];
  for (let i = 1; i <= size; i++) {
    arr.push(`${(page - 1) * size + i}`);
  }

  return arr;
};

const fetchList = page => {
  return new Promise(resolve => {
    setTimeout(() => {
      return resolve(generateList(page, pageSize));
    }, 1000);
  });
};

let options = {
  root: null,
  threshold: 0
};

function App() {
  const [page, setPage] = useState(1);
  const [fetching, setFetching] = useState(false);
  const [list, setlist] = useState(generateList(page, pageSize));

  const callback = entries => {
    if (entries[0].isIntersecting) {
      observerRef.current.unobserve(
        document.getElementById(`item_${list.length - threshold}`)
      );
      setFetching(true);
/* at this point neither the 'page' is latest nor the 'list'
*they both have the initial states.
*/
      fetchList(page + 1).then(res => {
        setFetching(false);
        setPage(page + 1);
        setlist([...list, ...res]);
      });
    }
  };

  const observerRef = useRef(new IntersectionObserver(callback, options));

  useEffect(() => {
    if (observerRef.current) {
      observerRef.current.observe(
        document.getElementById(`item_${list.length - threshold}`)
      );
    }
  }, [list]);

  return (
    <div className="App">
      {list.map(l => (
        <p key={l} id={`item_${l}`}>
          {l}
        </p>
      ))}
      {fetching && <p>loading...</p>}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

当前行为: “页面”和“列表”的值始终等于初始状态而不是最新值。第 2 页后无限滚动不起作用

预期行为:在回调函数中,它应该读取状态“页面”和“列表”的更新值。

这是这个演示 的工作沙箱https://codesandbox.io/s/sweet-sun-rbcml?fontsize=14&hidenavigation=1&theme=dark

丹尼斯·瓦什

这里主要有两个问题,闭包和直接查询 DOM。

要解决闭包问题,请使用函数useState和引用:

const listLengthRef = useRef(list.length);
const pageRef = useRef(page);

const callback = useCallback(entries => {
  if (entries[0].isIntersecting) {
    observerRef.current.unobserve(
      document.getElementById(`item_${listLengthRef.current - threshold}`)
    );
    setFetching(true);
    fetchList(pageRef.current + 1).then(res => {
      setFetching(false);
      setPage(page => page + 1);
      setlist(list => [...list, ...res]);
    });
  }
}, []);

const observerRef = useRef(new IntersectionObserver(callback, options));

useEffect(() => {
  listLengthRef.current = list.length;
}, [list]);

useEffect(() => {
  pageRef.current = page;
}, [page]);

尽管此代码有效,但您应该将其替换document.getElementById为引用,在这种情况下,它将是对页面最后一个元素的引用。

编辑frosty-smoke-if4il

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么第一次在父回调函数中没有更新子状态值?

即使状态值没有变化,也反应组件渲染

在使用钩子的反应中没有得到更新的状态值?

反应setState回调没有更新的状态

在简单组件中获取状态值 - 类 VS 功能(类工作,功能不工作)。为什么?

反应:将组件状态值复制到剪贴板,而没有虚拟元素

如何在没有任何新状态值的情况下将“ setState”作为回调函数成功更新状态?

为什么我不能从 useEffect 回调中更新我的组件的状态?

为什么用旧值调用useState的setter随后会触发组件更新,即使旧状态值等于新状态值

React-UseState-为什么setTimeout函数没有最新状态值?

为什么useState值在useHotkeys回调中未更新?

为什么我的回调没有在 Tensorflow 中调用?

为什么react-dnd useDrop挂钩中的回调函数无法更新父组件状态?

为什么组件在反应钩子中没有刷新?

为什么在反应组件中没有进行验证

为什么我的状态在我的组件中似乎没有更新?

为什么子组件在React Native中没有从父组件接收更新的值?

如何根据反应功能组件中的先前状态有条件地更新状态?

如何使用带有地图功能的状态值来显示React组件中的重复ui

React:从回调中设置功能组件的状态

反应在没有箭头功能的回调中访问setState

useState 钩子 - 传入回调与状态值

Javascript 回调未引用正确的状态值

为什么我的事件监听器回调没有使用正确的状态?

为什么异步验证程序回调将没有组件上下文?

更新的状态值不会在反应中的函数内部更新

onChange 在通过状态更新更改值时无法在反应功能组件中工作

无法在回调函数中更新组件的状态

为什么反应状态(useState)在记录时更新但没有更新?