英文:
How can I return children prop in react only after my useEffect code runs. (synchronous behaviour)
问题
我正在尝试为我的axios请求创建一个拦截器包装器,以处理JWT令牌。
我想要的是先在useEffect
块内运行拦截器代码,然后返回children
,以便children
带着新的访问令牌返回,最终完成成功的API调用。但是实际上我得到的是,它返回的是旧的JWT令牌,并且API调用会使用过期的令牌导致错误。
我还尝试添加一个状态,如下:
const [isSet, setIsSet] = useState<boolean>(false);
// ...
setIsSet(true)
// ...
return isSet && children;
但是 TypeScript 不允许我这样做。
如何解决这个问题?
英文:
I am trying to create axios interceptor wrapper for my axios request to handle JWT tokens.
What I want is to run the interceptor code first inside the useEffect block and then return children so that the children returns with new access token and eventually a successfull api call. but instead what I am getting is, it is returning with the old jwt token and the api call happens with an expired token resulting to an error.
const AxiosPrivateInterceptor: FC<IProps> = ({ children }) => {
const { user } = useAppSelector(selectAuthUser);
const refresh = useRefreshToken();
useEffect(() => {
const requestIntercept = axiosPrivate.interceptors.request.use(
(config: AxiosRequestConfig) => {
config.headers = config.headers ?? {};
if (!config?.headers["Authorization"]) {
config.headers["Authorization"] = `Bearer ${user?.accessToken}`;
}
return config;
},
(error) => Promise.reject(error)
);
const responseIntercept = axiosPrivate.interceptors.response.use(
(response) => response,
async (error) => {
const prevRequest = error?.config;
if (error?.response.status === 403 && !prevRequest?.sent) {
prevRequest.send = true;
const newToken = await refresh();
const accessToken = newToken.accessToken;
prevRequest.headers["Authorization"] = `Bearer ${accessToken}`;
return axiosPrivate(prevRequest);
}
return Promise.reject(error);
}
);
return () => {
axiosPrivate.interceptors.request.eject(requestIntercept);
axiosPrivate.interceptors.response.eject(responseIntercept);
};
}, [user, refresh]);
return children;
};
I also tried to add a state like this :
const AxiosPrivateInterceptor: FC<IProps> = ({ children }) => {
const { user } = useAppSelector(selectAuthUser);
const refresh = useRefreshToken();
const [isSet, setIsSet] = useState<boolean>(false);
useEffect(() => {
const requestIntercept = axiosPrivate.interceptors.request.use(
(config: AxiosRequestConfig) => {
config.headers = config.headers ?? {};
if (!config?.headers["Authorization"]) {
config.headers["Authorization"] = `Bearer ${user?.accessToken}`;
}
return config;
},
(error) => Promise.reject(error)
);
const responseIntercept = axiosPrivate.interceptors.response.use(
(response) => response,
async (error) => {
const prevRequest = error?.config;
if (error?.response.status === 403 && !prevRequest?.sent) {
prevRequest.send = true;
const newToken = await refresh();
const accessToken = newToken.accessToken;
prevRequest.headers["Authorization"] = `Bearer ${accessToken}`;
return axiosPrivate(prevRequest);
}
return Promise.reject(error);
}
);
setIsSet(true)
return () => {
axiosPrivate.interceptors.request.eject(requestIntercept);
axiosPrivate.interceptors.response.eject(responseIntercept);
};
}, [user, refresh]);
return isSet && children;
};
But typescript won't allow me to do that.
How this issue can be solved?
答案1
得分: 1
虽然这没有解决我的主要问题,但我发现绕过这个 TypeScript 错误相当容易:
return <>{isSet && children}</>;
英文:
Although this did not fix my main issue, but I figured out that it's quite easy to bypass this typescript error:
return <>{isSet && children}</>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论