【问题标题】:calling setState() will execute the function value instead of passing it调用 setState() 将执行函数值而不是传递它
【发布时间】:2020-10-19 12:18:53
【问题描述】:

我有以下代码。按下按钮时,预期的行为是重新创建 AxiosInstance 并更新状态。但实际上,实例会被重新创建,然后在某处执行。

function createApi(): AxiosInstance {
  const api = axios.create();
  // ...
  return api;
}

function App() {
  const [api, setApi] = React.useState<AxiosInstance>(() => createApi());
  const resetApi = () => {
    setApi(createApi());
  };

  console.log(api);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={resetApi}>Reset API</button>
    </div>
  );
}

Typescript 没有错误,setApi 在我的 IDE 中有如下签名:

React.Dispatch<React.SetStateAction<AxiosInstance>>

这将被评估为如下内容:

(value: AxiosInstance) => void

这正是我在第一个代码 sn-p 中所做的,为什么它不起作用?

【问题讨论】:

    标签: reactjs typescript react-hooks


    【解决方案1】:

    好吧,很明显 Typescript 骗了我,事情没那么简单。 AxiosInstance 具有以下签名:

    export interface AxiosInstance {
      (config: AxiosRequestConfig): AxiosPromise;
      (url: string, config?: AxiosRequestConfig): AxiosPromise;
      ...
    }
    

    所以AxiosInstance 是一个functionuseState 在底层使用useReducer,在挖掘了 ReactJS 代码库之后,我found outuseReducer 中使用的调度函数只做了一个简单的检查接收到的值是一个泛型函数

    function basicStateReducer<S>(state: S, action: BasicStateAction<S>): S {
      return typeof action === 'function' ? action(state) : action;
    }
    

    所以调度错误AxiosInstance(它本身就是一个函数)因为它是一个回调函数,并直接执行它。

    修复很简单,通过回调返回实例而不是直接传入setState

    setApi(() => createApi())
    

    现场示例

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-05
      • 2019-04-18
      • 2015-04-21
      • 2018-11-22
      • 1970-01-01
      • 1970-01-01
      • 2011-10-29
      相关资源
      最近更新 更多