仅在效果的一个部门改变时,改变useEffect Hook [英] React useEffect Hook when only one of the effect's deps changes, but not the others

查看:48
本文介绍了仅在效果的一个部门改变时,改变useEffect Hook的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用Hooks的功能组件:

I have a functional component using Hooks:

function Component(props) {
  const [ items, setItems ] = useState([]);

  // In a callback Hook to prevent unnecessary re-renders 
  const handleFetchItems = useCallback(() => {
    fetchItemsFromApi().then(setItems);
  }, []);

  // Fetch items on mount
  useEffect(() => {
    handleFetchItems();
  }, []);

  // I want this effect to run only when 'props.itemId' changes,
  // not when 'items' changes
  useEffect(() => {
    if (items) {
      const item = items.find(item => item.id === props.itemId);
      console.log("Item changed to " item.name);
    }
  }, [ items, props.itemId ])

  // Clicking the button should NOT log anything to console
  return (
    <Button onClick={handleFetchItems}>Fetch items</Button>
  );
}

该组件会在安装时获取一些 item 并将其保存到状态.

The component fetches some items on mount and saves them to state.

组件从React Router接收到 itemId 道具.

The component receives an itemId prop (from React Router).

每当 props.itemId 更改时,我希望它触发一个效果,在这种情况下,将其记录到控制台.

Whenever the props.itemId changes, I want this to trigger an effect, in this case logging it to console.

问题在于,由于效果还取决于 items ,因此只要 items 发生更改(例如,当 items 按下按钮即可重新获取code.

The problem is that, since the effect is also dependent on items, the effect will also run whenever items changes, for instance when the items are re-fetched by pressing the button.

可以通过将先前的 props.itemId 存储在单独的状态变量中,然后将二者进行比较来解决此问题,但这似乎很简单,并且增加了样板.通过使用Component类,可以通过在 componentDidUpdate 中比较当前和以前的道具来解决,但是使用功能组件是不可能的,这是使用Hooks的要求.

This can be fixed by storing the previous props.itemId in a separate state variable and comparing the two, but this seems like a hack and adds boilerplate. Using Component classes this is solved by comparing current and previous props in componentDidUpdate, but this is not possible using functional components, which is a requirement for using Hooks.

仅当其中一个参数发生更改时,触发取决于多个参数的效果的最佳方法是什么?

PS.挂钩是一种新事物,我认为我们都在尽力找出如何正确使用挂钩的功能,因此,如果我的想法对您来说似乎是错误的或尴尬的,请指出.

推荐答案

React团队说,获取prev值的最佳方法是使用useRef:

The React Team says that the best way to get prev values is to use useRef: https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state

function Component(props) {
  const [ items, setItems ] = useState([]);

  const prevItemIdRef = useRef();
  useEffect(() => {
    prevItemIdRef.current = props.itemId;
  });
  const prevItemId = prevItemIdRef.current;

  // In a callback Hook to prevent unnecessary re-renders 
  const handleFetchItems = useCallback(() => {
    fetchItemsFromApi().then(setItems);
  }, []);

  // Fetch items on mount
  useEffect(() => {
    handleFetchItems();
  }, []);

  // I want this effect to run only when 'props.itemId' changes,
  // not when 'items' changes
  useEffect(() => {
    if(prevItemId !== props.itemId) {
      console.log('diff itemId');
    }

    if (items) {
      const item = items.find(item => item.id === props.itemId);
      console.log("Item changed to " item.name);
    }
  }, [ items, props.itemId ])

  // Clicking the button should NOT log anything to console
  return (
    <Button onClick={handleFetchItems}>Fetch items</Button>
  );
}

我认为这对您有帮助.

注意:如果不需要以前的值,另一种方法是为props.itemId写一个useEffect more

Note: if you don't need the previous value, another approach is to write one useEffect more for props.itemId

React.useEffect(() => {
  console.log('track changes for itemId');
}, [props.itemId]);

这篇关于仅在效果的一个部门改变时,改变useEffect Hook的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆