Skip to content

NylasScheduling (React): schedulerApiUrl wrong after full page refresh; client navigation / redirect OK #55

@Joee94

Description

@Joee94

Problem

NylasScheduling from @nylas/react does not reliably apply schedulerApiUrl before the Stencil element initializes. The nylas-scheduling host runs componentWillLoad when it connects and creates NylasSchedulerConnector using this.schedulerApiUrl. The React wrapper (via @stencil/react-output-target and @lit/react) applies element properties in useLayoutEffect, which runs after the node is inserted. The connector is therefore often created with the default API base (https://api.us.nylas.com) instead of the value passed from React.

What we see

  • After in-app navigation or a redirect to the page that hosts the scheduler, behavior looks correct (region / schedulerApiUrl as expected).
  • After a full page refresh on that same URL, behavior breaks (requests or connector behavior match the US default).

Expected

schedulerApiUrl (for example https://api.eu.nylas.com) should behave the same after a hard refresh as after client-side navigation.

Environment

  • next: 16.2.2
  • react: 19.2.4
  • react-dom: 19.2.4
  • @types/react: 19.2.8
  • @nylas/react: 3.2.0
  • @nylas/web-elements: 2.5.0 (pulled in by @nylas/react)
  • Next.js App Router; scheduler rendered from a client component
    Confirm exact Nylas versions with pnpm list @nylas/react @nylas/web-elements if needed.

Hypothesis

  1. Lit’s React integration sets custom-element properties after connect (useLayoutEffect).
  2. Stencil runs componentWillLoad on connect and builds the scheduler connector using schedulerApiUrl before those properties are applied.
  3. Cold load vs client navigation can change timing enough that the bug shows up mainly on refresh.

Workaround that works: client-only gate with isMounted + useEffect

We gated rendering of NylasScheduling so it only mounts after the browser has committed the first client pass, using local state flipped in useEffect:

  • Initialise something like isMounted to false.
  • In useEffect with an empty dependency array, set isMounted to true.
  • Until isMounted is true, render nothing (or a loading placeholder) instead of NylasScheduling.
    That pattern is useful when a custom element must not run during SSR, or when you want the scheduler to appear only after hydration. In our case it did not fully fix the wrong schedulerApiUrl on refresh, because the underlying issue is prop application timing relative to Stencil’s componentWillLoad, not only “first paint is server vs client.” It may still be worth documenting for others who combine Next.js, React 19, and Nylas, and as something to try alongside other mitigations (for example ensuring the API base is set on the element before it is inserted into the document).
    Example shape (illustrative only):
const [isMounted, setIsMounted] = useState(false);
useEffect(() => {
  setIsMounted(true);
}, []);
if (!isMounted) {
  return null;
}
return (
  <NylasScheduling
    configurationId={configurationId}
    schedulerApiUrl={schedulerApiUrl}
    /* … */
  />
);

However I don't believe this should be necessary for every user of this component to do

Links

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions