我有以下 React 组件,它的工作方式非常奇怪!
useEffect
钩子内的一切都是正确的(console.log显示了实例的正确值),但是在使用新创建的axios实例调用setApiInstance
之后,apiInstance
意外地变成了Promise对象,这是很不寻常的!
Codepen:https://codesandbox.io/p/sandbox/4j2dzs?file=%2Fsrc%2FApp.tsx%3A15%2C30
import React, { useEffect, useState } from "react";
import axios, { AxiosInstance } from "axios";
const MyComponent = ({ appConfig }: { appConfig: { host: string } }) => {
const [apiInstance, setApiInstance] = useState<AxiosInstance | null>(null);
useEffect(() => {
const instance = axios.create({
baseURL: appConfig.host,
});
console.log("instance", instance);
setApiInstance(instance);
}, [appConfig]);
console.log("apiInstance", apiInstance);
if (!apiInstance) return;
return null;
};
export default function App() {
return <MyComponent appConfig={{ host: "0.0.0.0" }} />;
}
但是如果我在
useState
初始化方法中创建 axios 实例,它就可以正常工作!
const [apiInstance, setApiInstance] = useState<AxiosInstance | null>(() => axios.create({
baseURL: appConfig.host,
params: { website_token: appConfig.websiteToken }
}));
你能帮我看看发生了什么事吗?
这是因为在 React 中,从
setState()
返回的
useState()
函数可以接受充当 状态设置器函数的函数,即:
setState(currState => newState);
在你的例子中,
instance
返回的axios.create()
是一个函数,因此当你将其传递给setApiInstance()
时,React将其视为状态设置函数。
您可以通过使用状态设置函数并返回实例来解决此问题:
setApiInstance(() => instance);
但是,我会质疑您是否需要首先将实例存储在此处的状态中。像这样的东西通常最好存储在 ref 中,因为你的 UI 很可能不需要使用/渲染你的实例:
const apiInstanceRef = useRef<AxiosInstance>();
useEffect(() => {
const instance = axios.create({
baseURL: appConfig.host,
});
apiInstanceRef.current = instance;
}, [appConfig]);