简体   繁体   English

React hooks:如何摆脱 state 依赖

[英]React hooks: how to get rid of a state dependency

In the exemple below, I wonder how to get rid of items dependency in the useEffect() I want to execute only once to set the interval.在下面的示例中,我想知道如何摆脱useEffect()中的items依赖性我只想执行一次以设置间隔。 What's the best practice around that?最好的做法是什么? Thanks!谢谢!

const Component = () => {
  const [items, setItems] = useState([])

  useEffect(() => {
    const fetchItems = () => {
      fetchNewItemsSince(items.length ? items[items.length - 1].id : 0) // How to get rid of items dependency
        .then((newItems) => {
          setItems((oldItems) => [...oldItems, ...newItems])
        })
    }

    fetchItems()
    setInterval(fetchItems, 60 * 10000)

    return () => clearInterval()
  }, [items]) // <= I want to get rid of that dependency!!
}

There are few mistakes in this snippets like cleaning the interval and calling the cleaning function in useEffect , I would re-write this logic to:这个片段中有一些错误,比如清理间隔和在 useEffect 中调用清理useEffect ,我会把这个逻辑重写为:

const Component = () => {
  const [items, setItems] = useState([]);
  const itemsRef = useRef(items);

  const fetchItems = useCallback(() => {
    const [first] = itemsRef.current;
    fetchNewItemsSince(first || 0).then((newItems) => {
      setItems((oldItems) => [...oldItems, ...newItems]);
    });
  }, []);

  // Update ref to dispose closure on `items` state
  useEffect(() => {
    itemsRef.current = items;
  }, [items]);

  // Call once on mount
  useEffect(() => {
    fetchItems();
  }, [fetchItems]);

  // Make an interval
  useEffect(() => {
    const id = setInterval(fetchItems, ONE_MINUTE);

    return () => {
      clearInterval(id);
    };
  }, [fetchItems]);
};

I'd do something like this, using the useInterval hook from the react-use library :我会做这样的事情,使用react-use库中的useInterval钩子

const Component = () => {
  const [items, setItems] = useState([]);
  const lastItemId = useMemo(
    () => (items.length ? items[items.length - 1].id : 0),
    [items],
  );
  const fetchNewItems = useCallback(async () => {
    const newItems = await fetchNewItemsSince(lastItemId);
    if(newItems.length) {
      setItems((oldItems) => [...oldItems, ...newItems]);
    }
  }, [lastItemId, setItems]);
  useInterval(fetchNewItems, 60 * 10000);
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM