4

I am building my web application's frontend using NextJs. My client is running at http://localhost:3000/ and my graphql server is at http://localhost:5000/graphql. So I was creating Urql client and I want server side rendering. In my index.tsx I created the urql client using withUrqlClient and specified proper url for my backend:

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((ssrExchange: 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,
                  };
                }
              }
            );
          },
          .
          .
          .
      },
    }),
    ssrExchange,
    fetchExchange,
  ],
}))(Index);

The problem is, when I go to /login page (or any page aside from index), and make a submit request on login form, it makes request to http://localhost:3000. I get the warning on console:

I don't think that error is in the 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.

Can anyone please explain whats going on ? I followed the documentation as it is: https://formidable.com/open-source/urql/docs/advanced/server-side-rendering/#nextjs

Just for reference, here's my _app.tsx

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

export default MyApp;

Is there a wrapper around the application that I am missing ?

Arjun Kashyap
  • 623
  • 2
  • 10
  • 24

2 Answers2

1

Wrapping Login component export as follows worked well for me.

export default withUrqlClient((ssrExchange: any) => ({...})(Login)

I think there is a better way to solve it

maga42
  • 43
  • 1
  • 7
1

Had the same issue and spent a lot of time without being able to solve it. I came around it by using withUrqlClient on the app component in _app.tsx which defeats the purpose and does not allow to select pages to ssr or not.

G-8
  • 107
  • 1
  • 7