You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复TypeScript报错:Context Provider的value数组每次渲染变化

React Context Provider 类型错误与性能警告解决方法

问题场景

我编写了以下React Context与Provider代码:

const SearchParamsStateProvider = ({
  children,
}: {
  children: React.ReactNode;
}) => {
  const [searchParams, setSearchParams] = useSearchParams();

  return (
    <SearchParamsStateContext.Provider value={[searchParams, setSearchParams]}>
      {children}
    </SearchParamsStateContext.Provider>
  );
};

const SearchParamsStateContext = createContext<
  [searchParams: URLSearchParams, setSearchParams: SetURLSearchParams]
>([
  new URLSearchParams(''),
  (
    search?:
      | URLSearchParamsInit
      | ((prev: URLSearchParams) => URLSearchParamsInit),
  ) => search,
]);

TypeScript在value={[searchParams, setSearchParams]}行抛出性能警告:

The array passed as the value prop to the Context provider (at line
12) changes every render. To fix this consider wrapping it in a
useMemo hook.

尝试用useMemo优化后:

const value = useMemo(
    () => [searchParams, setSearchParams],
    [searchParams, setSearchParams],
  );

  return (
    <SearchParamsStateContext.Provider value={value}>
      {children}
    </SearchParamsStateContext.Provider>
  );

又出现类型错误:

Type '(URLSearchParams | SetURLSearchParams)[]' is not assignable to type '[searchParams: URLSearchParams, setSearchParams: SetURLSearchParams]'.
  Target requires 2 element(s) but source may have fewer.

解决方案

方法1:显式断言元组类型

TypeScript默认会把[searchParams, setSearchParams]推断为联合类型数组,而非严格元组。可以通过类型断言强制指定为定义好的元组类型:

const value = useMemo(
  () => [searchParams, setSearchParams] as [URLSearchParams, SetURLSearchParams],
  [searchParams, setSearchParams],
);

或者复用Context的默认值类型,避免重复编写类型:

const value = useMemo(
  () => [searchParams, setSearchParams] as typeof SearchParamsStateContext.defaultValue,
  [searchParams, setSearchParams],
);

方法2:改用对象传递上下文

元组的类型推断容易出现歧义,换成对象结构可以让TypeScript更清晰识别类型,同时提升上下文使用的可读性:
首先修改Context定义:

const SearchParamsStateContext = createContext<{
  searchParams: URLSearchParams;
  setSearchParams: SetURLSearchParams;
}>({
  searchParams: new URLSearchParams(''),
  setSearchParams: (search?: URLSearchParamsInit | ((prev: URLSearchParams) => URLSearchParamsInit)) => search,
});

然后在Provider中使用对象:

const value = useMemo(
  () => ({ searchParams, setSearchParams }),
  [searchParams, setSearchParams],
);

return (
  <SearchParamsStateContext.Provider value={value}>
    {children}
  </SearchParamsStateContext.Provider>
);

方法3:指定useMemo的泛型参数

直接给useMemo指定泛型,明确它返回的是严格元组类型:

const value = useMemo<[URLSearchParams, SetURLSearchParams]>(
  () => [searchParams, setSearchParams],
  [searchParams, setSearchParams],
);

以上三种方法都能解决类型错误,同时消除性能警告。如果追求代码可读性,推荐使用方法2;如果想保留元组结构,方法1或3均可。

内容的提问来源于stack exchange,提问作者Croviajo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:58:10