React 自定义钩子与 useReducer
React custom hook vs useReducer
我已经创建了自己的 React Hook,但是当我使用自定义挂钩中的函数时,我收到了 React Hook useEffect has a missing dependency: 'setPlayer'. Either include it or remove the dependency array
警告。
我试图从钩子中提取函数以避免 React 在每次渲染时创建一个新的函数实例,也尝试了 useCallback
,但仍然有同样的问题。
当我使用 useReducer
时,我可以在我的 useEffect
中使用 dispatch
而没有任何警告,究竟有什么区别?
我的带有警告的自定义钩子 :
export function usePlayer() {
const playerService = useRef<PlayerService>();
const setPlayer = useCallback((youtubePlayer: YouTubePlayer) => {
playerService.current = new YoutubePlayerService(youtubePlayer);
}, []);
// also tried
/**
function setPlayer(youtubePlayer: YouTubePlayer) {
playerService.current = new YoutubePlayerService(youtubePlayer);
}
and putting `setPlayer outside of the hook`
**/
const getPlayerService = useCallback(() => {
return playerService.current;
}, []);
return [getPlayerService, setPlayer]
}
export function Component() {
const [setPlayer] = usePlayer();
const [youtubePlayer, setYoutubePlayer] = useState<YouTubePlayer>(undefined);
useEffect(() => {
setPlayer(youtubePlayer);
}, [youtubePlayer]
//React Hook useEffect has a missing dependency: 'setPlayer'. Either include it or remove the dependency array
}
也尝试过:
let currentPlayerService = undefined;
function setPlayer(youtubePlayer: YouTubePlayer) {
currentPlayerService = new YoutubePlayerService(youtubePlayer);
}
export function usePlayer() {
return [currentPlayerService, setPlayer];
}
例如,当我使用 useReducer
中的 dispatch
时,我没有收到此警告 (https://fr.reactjs.org/docs/hooks-reference.html#usereducer)
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
dispatch({type: 'increment'})
}, [state])
// no warning with dispatch <<
return (
<>
Total : {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
如何实现同一种Hook(我的函数没有警告)?
(试图深入实施,但没有帮助 https://github.com/facebook/react/blob/6ecad79ccf2c683cb21ac40dee5678358c7b6208/packages/react/src/ReactHooks.js#L24)
您看到的错误是一个 eslint 规则,警告您 react 挂钩依赖项数组中缺少依赖项。它告诉您应该在依赖项列表中包含 setPlayer
因为它无法判断它是否是稳定的引用。它没有从useReducer
抱怨dispatch
的原因是因为useReducer
及其功能是explicitly handled in the eslint rule。 Eslint 不知道你的函数是稳定的,但你知道,所以将它放入依赖数组并消除错误是安全的。
我不知道这是否是您发出警告的原因,但我可以在您的代码中看到一个小错误。您在挂钩 return [getPlayerService, setPlayer]
中返回一个数组。当试图解构它时,你就像它是一个对象一样。对于一个对象,您可以像在此处所做的那样对其进行解构 const [setPlayer] = usePlayer();
因为它由键值对组成(您也应该将 [] 换成 {} )。但是解构数组,是基于它们的索引和它们的序列。因此,当您只取回其中一项时,它将是数组中索引为 0 的第一项。因此,您解构的 setPlayer 确实是您的 getPlayerService 方法。
我已经创建了自己的 React Hook,但是当我使用自定义挂钩中的函数时,我收到了 React Hook useEffect has a missing dependency: 'setPlayer'. Either include it or remove the dependency array
警告。
我试图从钩子中提取函数以避免 React 在每次渲染时创建一个新的函数实例,也尝试了 useCallback
,但仍然有同样的问题。
当我使用 useReducer
时,我可以在我的 useEffect
中使用 dispatch
而没有任何警告,究竟有什么区别?
我的带有警告的自定义钩子 :
export function usePlayer() {
const playerService = useRef<PlayerService>();
const setPlayer = useCallback((youtubePlayer: YouTubePlayer) => {
playerService.current = new YoutubePlayerService(youtubePlayer);
}, []);
// also tried
/**
function setPlayer(youtubePlayer: YouTubePlayer) {
playerService.current = new YoutubePlayerService(youtubePlayer);
}
and putting `setPlayer outside of the hook`
**/
const getPlayerService = useCallback(() => {
return playerService.current;
}, []);
return [getPlayerService, setPlayer]
}
export function Component() {
const [setPlayer] = usePlayer();
const [youtubePlayer, setYoutubePlayer] = useState<YouTubePlayer>(undefined);
useEffect(() => {
setPlayer(youtubePlayer);
}, [youtubePlayer]
//React Hook useEffect has a missing dependency: 'setPlayer'. Either include it or remove the dependency array
}
也尝试过:
let currentPlayerService = undefined;
function setPlayer(youtubePlayer: YouTubePlayer) {
currentPlayerService = new YoutubePlayerService(youtubePlayer);
}
export function usePlayer() {
return [currentPlayerService, setPlayer];
}
例如,当我使用 useReducer
中的 dispatch
时,我没有收到此警告 (https://fr.reactjs.org/docs/hooks-reference.html#usereducer)
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
useEffect(() => {
dispatch({type: 'increment'})
}, [state])
// no warning with dispatch <<
return (
<>
Total : {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
如何实现同一种Hook(我的函数没有警告)? (试图深入实施,但没有帮助 https://github.com/facebook/react/blob/6ecad79ccf2c683cb21ac40dee5678358c7b6208/packages/react/src/ReactHooks.js#L24)
您看到的错误是一个 eslint 规则,警告您 react 挂钩依赖项数组中缺少依赖项。它告诉您应该在依赖项列表中包含 setPlayer
因为它无法判断它是否是稳定的引用。它没有从useReducer
抱怨dispatch
的原因是因为useReducer
及其功能是explicitly handled in the eslint rule。 Eslint 不知道你的函数是稳定的,但你知道,所以将它放入依赖数组并消除错误是安全的。
我不知道这是否是您发出警告的原因,但我可以在您的代码中看到一个小错误。您在挂钩 return [getPlayerService, setPlayer]
中返回一个数组。当试图解构它时,你就像它是一个对象一样。对于一个对象,您可以像在此处所做的那样对其进行解构 const [setPlayer] = usePlayer();
因为它由键值对组成(您也应该将 [] 换成 {} )。但是解构数组,是基于它们的索引和它们的序列。因此,当您只取回其中一项时,它将是数组中索引为 0 的第一项。因此,您解构的 setPlayer 确实是您的 getPlayerService 方法。