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 方法。