为啥使用服务器端渲染时 urql 在错误的地址发出请求?

Posted

技术标签:

【中文标题】为啥使用服务器端渲染时 urql 在错误的地址发出请求?【英文标题】:Why is urql making request at wrong adress when I use server side rendering?为什么使用服务器端渲染时 urql 在错误的地址发出请求? 【发布时间】:2021-06-17 16:15:57 【问题描述】:

我正在使用 NextJs 构建我的 Web 应用程序的前端。我的客户端在http://localhost:3000/ 运行,我的graphql 服务器在http://localhost:5000/graphql。所以我正在创建 Urql 客户端,我想要服务器端渲染。在我的 index.tsx 中,我使用 withUrqlClient 创建了 urql 客户端,并为我的后端指定了正确的 url:

const Index = () => 
  return (
    <div>
      <Head>
        <meta
          name="viewport"
          content="minimum-scale=1, initial-scale=1, width=device-width"
        />
      </Head>
      <Navbar />
      <h1>Hello stc</h1>
    </div>
  );
;

// create urql client
export default withUrqlClient((s-s-rExchange: any) => (

  url: "http://localhost:5000/graphql",   
  exchanges: [
    dedupExchange,
    cacheExchange(
      updates: 
        Mutation: 
          loginUser: (_result, _args, cache) => 
            customUpdateQuery<LoginMutation, MeQuery>(
              cache,
               query: MeDocument ,
              _result,
              (result, query) => 
                if (result.loginUser.errors) 
                  return query;
                 else 
                  return 
                    me: result.loginUser.user,
                  ;
                
              
            );
          ,
          registerUser: (_result, _args, cache) => 
            customUpdateQuery<RegisterMutation, MeQuery>(
              cache,
               query: MeDocument ,
              _result,
              (result, query) => 
                if (result.registerUser.errors) 
                  return query;
                 else 
                  return 
                    me: result.registerUser.user,
                  ;
                
              
            );
          ,
          .
          .
          .
      ,
    ),
    s-s-rExchange,
    fetchExchange,
  ],
))(Index);

问题是,当我转到/login 页面(或除索引之外的任何页面)并在登录表单上提出提交请求时,它会向http://localhost:3000 发出请求。我在控制台上收到警告:

我认为 login.tsx 中没有错误

Login.tsx

interface FormValues 
  usernameOrEmail: string;
  password: string;


// initial values for form
const initialValues: FormValues = 
  usernameOrEmail: "",
  password: "",
;

const loginSchema = yup.object().shape(
  usernameOrEmail: yup.string().required("Required"),
  password: yup.string().required("Required"),
);

const login: React.FC<loginProps> = () => 
  const router = useRouter();
  const [isLoading, setIsLoading] = useState<boolean>(false);
  const [, login] = useLoginMutation();
  return (
    <div>
      <NavBar />

      <Wrapper variant="small">

        <Formik
          initialValues=initialValues
          onSubmit=async (values: FormValues,  setErrors ) => 
            setIsLoading(true);
            // Make register mutation
            const response = await login(
              details: 
                usernameOrEmail: values.usernameOrEmail,
                password: values.password,
              ,
            );
            // Handle errors
            if (response.data?.loginUser.errors) 
              setErrors(toErrorMaps(response.data.loginUser.errors));
             else 
              // if no errors, re route to home page
              router.push("/");
            
            setIsLoading(false);

            // Handle errors
            if (response.data?.loginUser.errors) 
              setErrors(toErrorMaps(response.data.loginUser.errors));
             else 
              // if no errors, re route to home page
              router.push("/");
            
          
          validationSchema=loginSchema
        >
          ( isValid, dirty ) => (
            <Form autoComplete="off">
              /* <LinearProgress /> */
              <FormikField
                name="usernameOrEmail"
                label="Username or Email"
                type="text"
              />

              <FormikField name="password" label="Password" type="password" />

              <Button
                variant="contained"
                color="primary"
                // disabled=!dirty||  || !isValid
                disabled=!dirty || !isValid || isLoading
                type="submit"
                fullWidth
              >
                Login
              </Button>
              isLoading ? <LinearProgress color="primary" /> : <div></div>
            </Form>
          )
        </Formik>
      </Wrapper>
    </div>
  );
;

export default login;



Default Client: No client has been specified using urql's Provider.This means that urql will be 
falling back to defaults including making requests to `/graphql`.
If that's not what you want, please create a client and add a Provider.

谁能解释一下发生了什么?我按照原样遵循了文档:https://formidable.com/open-source/urql/docs/advanced/server-side-rendering/#nextjs

仅供参考,这是我的_app.tsx

  function MyApp( Component, pageProps ) 
  return (
    <MuiThemeProvider theme=customTheme>
      <Component ...pageProps />
    </MuiThemeProvider>
  );


export default MyApp;

我缺少的应用程序是否有包装器?

【问题讨论】:

你清除缓存了吗? 我做到了。 . .它仍然向错误的地址发出请求 你应该用withUrqlClient 包裹你的_app 组件,所以它对所有页面都可用。 【参考方案1】:

如下包装登录组件导出对我来说效果很好。

export default withUrqlClient((s-s-rExchange: any) =&gt; (...)(Login)

我认为有更好的方法来解决它

【讨论】:

【参考方案2】:

遇到了同样的问题,花了很多时间却无法解决。我通过在_app.tsx 的应用程序组件上使用withUrqlClient 来解决这个问题,这违背了目的并且不允许选择页面到s-s-r 与否。

【讨论】:

以上是关于为啥使用服务器端渲染时 urql 在错误的地址发出请求?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Chrome 会删除 localhost:80 的端口号?

为啥我不能为我的 React 服务器端渲染应用导入 CSS 文件?

为啥我在尝试在 iOS Swift 中向服务器发出 post 请求时收到此错误:在展开 Optional 值时意外发现 nil?

urql useQuery 的暂停选项不会暂时冻结请求

React/Redux 服务端渲染初始状态

为啥我的服务器没有监听客户端发出的数据?