我正在嘗試學習 Ben Awad 的 lireddit 教程。
他展示了如何制作一個實用程式檔案來顯示整個應用程式的任何認證錯誤。
我認為自從他制作視頻以來,next/router的情況可能已經發生了變化。我正在努力找出一種方法,以這種方式在一個鉤子內、在一個組件內使用路由器來重定向。
我無法將 useRouter 鉤子放在 exchangeError 內 - 我認為原因在于,當我想在其他組件內使用 exchangeError 時,鉤子不再位于頂層,但我無法想出如何讓 exchangeError 在沒有它的情況下作業,或者適應 next/router 的 udpated 版本。
我最好的嘗試(我知道我不能這樣使用它)如下:
import { dedupExchange, fetchExchange, createClient, Exchange } from "urql"。
import { pipe, tap } from 'wonka'
import { useRouter } 來自 'next/router'
const errorExchange: Exchange = ({ forward }) => (ops$) => {
//我可以把這個放在哪里?
// const Router = useRouter();
return pipe(
forward(OPS$)。
tap(({ error }) => {
if (error?.message.includes("not authenticated") {
// Router.replace("/auth/login");.
}
})
);
};
本在lireddit發表的版本是:
const errorExchange。Exchange = ({ forward }) => (ops$) => /span> {
return pipe(
forward(OPS$)。
tap(({ error }) => {
if (error?.message.includes("not authenticated") {
Router.replace("/login"/span>)。
}
})
);
};
整個實用程式檔案如下:
import { dedupExchange, fetchExchange, createClient, Exchange } from "urql"。
import { cacheExchange } from '@urql/exchange-graphcache'
import { MeDocument, LoginMutation, RegisterMutation, MeQuery, LogoutMutation } from ".../generated/graphql"
import { betterUpdateQuery } from ' ./utils/betterUpdateQuery'
import { pipe, tap } from 'wonka'
import { useRouter } 來自 'next/router'
const errorExchange: Exchange = ({ forward }) => (ops$) => {
//我可以把這個放在哪里?
// const Router = useRouter();
return pipe(
forward(OPS$)。
tap(({ error }) => {
if (error?.message.includes("not authenticated") {
// Router.replace("/auth/login");.
}
})
);
};
export const createUrqlClient = (ssrExchange: any) => (
{
url: 'http://localhost:4000/graphql'。
fetchOptions: {
credentials: 'include' as const,
},
exchanges: [
dedupExchange。
cacheExchange({
updates: {
Mutation: {
logout: (_result, args, cache, info) => {
betterUpdateQuery<LogoutMutation, MeQuery> (
快取。
{query: MeDocument}。
_result,
(result, query) => ({me: null})
)
},
login: (_result, args, cache, info) => {
betterUpdateQuery<LoginMutation, MeQuery> (
快取。
{ query: MeDocument },
_result,
(result, query) => {
if (result.login.errors) {
return查詢。
} else {
return {
me: result.login.user。
};
}
}
);
},
register: (_result, args, cache, info) => {
betterUpdateQuery<RegisterMutation, MeQuery> (
快取。
{ query: MeDocument },
_result,
(result, query) => {
if (result.register.errors) {
return查詢。
} else {
return {
me: result.register.user。
};
}
}
);
},
},
},
}),
errorExchange。
ssrExchange,
fetchExchange。
],
}
)
然后,在創建帖子的表單中,這個實用程式被使用如下:
import { withUrqlClient } from "next-urql"/span>;
import { useRouter } from "next/router"/span>;
import React from "react"。
import { useCreatePostMutation } from "./generated/graphql";
import { createUrqlClient } from "./utils/createUrqlClient";
import { useIsAuth } from "./utils/useIsAuth"。
const CreatePost。React.FC<{}> = ({}) => {
// const router = useRouter();
// useIsAuth();
const [, createPost] = useCreatePostMutation();
return (
<Layout variant="small">
<Formik
initialValues={{標題。"", text: "" }}
onSubmit={async (values) => {
const { error } = await createPost({ input: values });
if (!error) {
router.push("/")。
}
}}
>
export default withUrqlClient(createUrqlClient)(CreatePost);
uj5u.com熱心網友回復:
所以我花了一些時間潛心研究源代碼。結論是:
import { dedupExchange, fetchExchange, createClient, Exchange } from "urql"。
import { pipe, tap } from 'wonka'
import Router from 'Next/router'
const errorExchange: Exchange = ({ forward }) => (ops$) => /span> {
return pipe(
forward(OPS$)。
tap(({ error }) => {
if (error?.message.includes("not authenticated") {
Router.router。 replace("/auth/login"); // <-- `Router.router`是方式。
}
})
);
};
我不知道他們為什么決定以這種方式暴露 API。Router.router在我看來非常奇怪,但這就是解決方案。
注意為什么
useRouter鉤子不是一個選項。
鉤子必須在一個反應組件實體中呼叫。但是errorExchange是由createUrqlClient呼叫的,而后者又是由withUrqlClient(createUrqlClient)(CreatePost)呼叫。
withUrlClient是一個裝飾器,或者說是 react 術語中的 HOC,并且所以我檢查了它呼叫errorExchange的時間對于鉤子函式的介入是不正確的,因此是個死胡同。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/322738.html
標籤:
