根据我的经验,不典型的做法是通过props
传递未被记忆化的函数。
<Wrapper
getWebsites={() => fetchJson('websites').then(setWebsites)}
loadUserRatings={() => fetchJson('ratings').then(setUserRatings)}
/>
如果它们被正确地记忆化(使用像
useCallback()
这样的钩子,或者在任何组件外定义),那么将它们传递给
useEffect()
的
deps
是安全的,而不会影响行为。以下是修复上述情况的示例。
const fetchJson = (...args) => fetch(...args).then(res => res.json());
const Parent = () => {
const [websites, setWebsites] = useState([]);
const [userRatings, setUserRatings] = useState({});
const getWebsites = useCallback(
() => fetchJson('websites').then(setWebsites),
[setWebsites]
);
const loadUserRatings = useCallback(
() => fetchJson('ratings').then(setUserRatings),
[setUserRatings]
);
...
<Wrapper
getWebsites={getWebsites}
loadUserRatings={loadUserRatings}
/>
* useState()
函数在其返回值中记录了调度函数的值,因此从技术上讲,在每个useCallback()
中将[]
作为deps
传递是安全的,但我认为将调度函数指定为依赖项有助于通过明确传达作者的意图来提高清晰度,并且没有传递它们的缺点。
Ramesh的回答已足够应对这种情况。
如果你发现自己卡在第一种情况中,则可以像这样将props
初始化到组件的状态中作为最后的选择。
const Wrapper = (props) => {
const [{ getWebsites, loadUserRatings }] = useState(props);
useEffect(() => {
getWebsites();
loadUserRatings();
}, [getWebsites, loadUserRatings]);
return (
<>
<Header />
<Websites />
<Sync />
</>
);
};