首页 > 解决方案 > 我可以忽略 useContext 的详尽警告吗?

问题描述

在我的 react-typescript 应用程序中,我正在尝试使用一个上下文提供程序来封装属性和方法并将它们公开给消费者:

const StockPriceConsumer: React.FC = () => {
  const stockPrice = useContext(myContext);
  let val = stockPrice.val;
  useEffect(() => {
    stockPrice.fetch();
  }, [val]);
  return <h1>{val}</h1>;
};

问题是以下警告:

React Hook useEffect 缺少依赖项:'stockPrice'。包括它或删除依赖数组。eslint(react-hooks/exhaustive-deps)

stockPrice对我来说,将(基本上是提供者的 API)包含到 useEffect 的依赖项中没有任何意义。只有包含股票价格的实际价值以防止无限调用 useEffect 函数才有意义。

问题:我尝试使用的方法有什么问题,或者我可以忽略这个警告吗?


提供者:

interface StockPrice {
  val: number;
  fetch: () => void;
}

const initialStockPrice = {val: NaN, fetch: () => {}};

type Action = {
  type: string;
  payload: any;
};

const stockPriceReducer = (state: StockPrice, action: Action): StockPrice => {
  if (action.type === 'fetch') {
    return {...state, val: action.payload};
  }
  return {...state};
};

const myContext = React.createContext<StockPrice>(initialStockPrice);

const StockPriceProvider: React.FC = ({children}) => {
  const [state, dispatch] = React.useReducer(stockPriceReducer, initialStockPrice);
  const contextVal  = {
    ...state,
    fetch: (): void => {
      setTimeout(() => {
        dispatch({type: 'fetch', payload: 200});
      }, 200);
    },
  };
  return <myContext.Provider value={contextVal}>{children}</myContext.Provider>;
};

标签: reactjsreact-contextuse-effectuse-reducer

解决方案


我建议从提供者控制整个获取逻辑:

const StockPriceProvider = ({children}) => {
  const [price, setPrice] = React.useState(NaN);

  useEffect(() => {
    const fetchPrice = () => {
      window.fetch('http...')
       .then(response => response.json())
       .then(data => setPrice(data.price))
    }
    const intervalId = setInterval(fetchPrice, 200)
    return () => clearInterval(intervalId)
  }, [])

  return <myContext.Provider value={price}>{children}</myContext.Provider>;
};

const StockPriceConsumer = () => {
  const stockPrice = useContext(myContext);
  return <h1>{stockPrice}</h1>;
};

...作为原始方法中几个问题的解决方案:

  1. 你真的想只取val不同的东西吗?如果 2 次渲染之间的股票价格相同,则不会执行 useEffect。
  2. fetch每次<StockPriceProvider>渲染都需要创建一个新方法吗?这确实不适合 useEffect 的依赖关系。

    • 如果两者都可以,请随意禁用 eslint 警告
    • 如果您想在安装了消费者后以 200 毫秒的间隔继续获取:
  // StockPriceProvider
  ...
    fetch: useCallback(() => dispatch({type: 'fetch', payload: 200}), [])
  ...
  // StockPriceConsumer
  ...
    useEffect(() => {
      const i = setInterval(fetch, 200)
      return () => clearInterval(i)
    }, [fetch])
  ...

推荐阅读