get-convex / convex-js

TypeScript/JavaScript client library for Convex
https://docs.convex.dev
Apache License 2.0
108 stars 12 forks source link

Add 'use client' to auth_helpers #11

Open RubenPera opened 7 months ago

RubenPera commented 7 months ago

Added 'use client' directive to auth_helpers, fixes #10

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

RubenPera commented 7 months ago

Hey @thomasballinger, could you merge this pull request please?

RubenPera commented 7 months ago

hey @thomasballinger I know this Pull request is not a big deal, but could you perhaps take a look at it (and please merge it)? 😄

thomasballinger commented 7 months ago

Hey @RubenPera , thanks for submitting.

Currently our Next.js quickstart recommends creating a "use client" component to contain the Convex provider and all client code. This change would mean this isn't necessary anymore, at least for Authentication components. If we make this change we should probably do it for the ConvexProvider as well, yeah? Right now the rules are consistent, you always need to wrap the Convex components in a "use client" wrapper component. My understanding is we should probably do this for all Convex components or none, what do you think?

Also have you tested this change? The last time I tried this there was some dance (it might have been avoiding export * from "./auth_helpers.js" in the index.js barrel file?) we had to do for the bundler that Next.js uses, but that was a while ago when this "use client" stuff was very new.

RubenPera commented 7 months ago

Hey @thomasballinger thanks for your extensive reply and working on this amazing project!

In Nextjs components can run on the client or on the server, which you can indicate using "use client" or "use server", where by default in Nextjs they run on the server which is great for loading data from the db and rendering the page on the server. However when accessing state or context, which only exist on the client, you need that a component is rendered on the client, which can be done in a component itself or in any of its parent components.

So I have the following example:

export default async function Page() {
const preloadedData = await preloadQuery(...);

return <ServerComponent>
  <Authenticated>
    <ClientComponent preloadedData={preloadedData} />
  </Authenticated>
</ServerComponent>
}

This will currently not work because the page is a server component by default, but the Authenticated component accesses the client logic so it must be rendered on the client. Right now I have a wrapper around the Authenticated component that has the 'use client' at the top of the file and that also just works.

And to keep consistency I would also add 'use client' to the context provider and all other components that require to be run on the client!

Hope this answers your question! 😃