仅在效果的一个部门改变时,改变useEffect Hook [英] React useEffect Hook when only one of the effect's deps changes, but not the others
问题描述
我有一个使用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屋!