important
This is a contributors guide and NOT a user guide. Please visit these docs if you are using or evaluating SuperTokens.
Split recipe-specific route handlers into separate components
Status
This is just a proposal so far, it hasn't been accepted and needs further discussion.
- Status:
- proposed
- Deciders:
- rishabhpoddar, porcellus
- Proposed by:
- porcellus
- Created:
- 2023-01-24
Context and Problem Statement#
We want to enable apps to initialize supertokens-auth-react without bundling react. This is useful for example in angular apps, where we should be able to use a single init call in the main route (and use auth-react throughout the app), while only bundling react to the module handling auth.
Considered Options#
- Add recipeIds into input of getRoutingComponent
- Add separate components for the pre-built UI of each recipe
Decision Outcome#
Chosen option: Add recipe specific UI classes into input of getRoutingComponent
- Works with most bundlers
- Works with react-router-dom
- Less interface change
Notes:
- The new classes will be called RecipeNamePreBuiltUI
- We choose not to handle component overrides in the new Routes components, in order to avoid multiple ways of adding the same config.
- canHandleRoutewill also take a list of UIs
- We can remove disableDefaultUIfrom the email verification config, but other recipes use this on a per-feature basis (e.g.: disable only signInUp instead of all pre-built routes).
Pros and Cons of the Options#
Add recipeIds into input of getRoutingComponent#
function App() {
  return (
    <SuperTokensWrapper>
      <EmailVerificationComponentsOverrideProvider
        components={{
          EmailVerificationSendVerifyEmail_Override: () => <OtpScreen />,
        }}>
        <div className="App">
          <Router>
            <Routes>
              {getSuperTokensRoutesForReactRouterDom(require("react-router-dom"), [EmailPassword.recipeId])}
              <Route
                path="/"
                element={
                  <SessionAuth>
                    <Home />
                  </SessionAuth>
                }
              />
            </Routes>
          </Router>
        </div>
      </EmailVerificationComponentsOverrideProvider>
    </SuperTokensWrapper>
  );
}
Add separate components for the pre-built UI of each recipe#
important
This was scrapped, because react-router-dom v6 requires you to add the route components as direct children of <Routes>
With react-router-dom:
function App() {
  return (
    <SuperTokensWrapper>
      <EmailVerificationComponentsOverrideProvider
        components={{
          EmailVerificationSendVerifyEmail_Override: () => <OtpScreen />,
        }}>
        <div className="App">
          <Router>
            <Routes>
              <EmailPasswordPreBuiltUIRoutes router={require("react-router-dom")} />
              <EmailVerificationPreBuiltUIRoutes router={require("react-router-dom")} />
              <Route
                path="/"
                element={
                  <SessionAuth>
                    <Home />
                  </SessionAuth>
                }
              />
            </Routes>
          </Router>
        </div>
      </EmailVerificationComponentsOverrideProvider>
    </SuperTokensWrapper>
  );
}
With no react-router-dom:
class App extends React.Component {
  render() {
    // We could handle looping through these for the user but I don't think this is an issue.
    if (EmailPasswordPreBuiltUI.canHandleRoute()) {
      return EmailPasswordPreBuiltUI.getRoutingComponent();
    }
    if (EmailVerificationPreBuiltUI.canHandleRoute()) {
      return (
        <EmailVerificationComponentsOverrideProvider
          components={{
            EmailVerificationSendVerifyEmail_Override: () => <OtpScreen />,
          }}>
          {EmailVerificationPreBuiltUI.getRoutingComponent()}
        </EmailVerificationComponentsOverrideProvider>
      );
    }
    return <SuperTokensWrapper>{/*Your app*/}</SuperTokensWrapper>;
  }
}
Add recipe specific UI classes into input of getRoutingComponent#
With react-router-dom:
function App() {
  return (
    <SuperTokensWrapper>
      <EmailVerificationComponentsOverrideProvider
        components={{
          EmailVerificationSendVerifyEmail_Override: () => <OtpScreen />,
        }}>
        <div className="App">
          <Router>
            <Routes>
              {getSuperTokensRoutesForReactRouterDom(reactRouterDom, [EmailPasswordPreBuiltUIRoutes, EmailVerificationPreBuiltUIRoutes])}
              <Route
                path="/"
                element={
                  <SessionAuth>
                    <Home />
                  </SessionAuth>
                }
              />
            </Routes>
          </Router>
        </div>
      </EmailVerificationComponentsOverrideProvider>
    </SuperTokensWrapper>
  );
}
With no react-router-dom:
class App extends React.Component {
  render() {
    // We could handle looping through these for the user but I don't think this is an issue.
    if (canHandleRoute([EmailPasswordPreBuiltUI])) {
      return getRoutingComponent([EmailPasswordPreBuiltUI]);
    }
    if (canHandleRoute([EmailPasswordPreBuiltUI])) {
      return (
        <EmailVerificationComponentsOverrideProvider
          components={{
            EmailVerificationSendVerifyEmail_Override: () => <OtpScreen />,
          }}>
          {getRoutingComponent([EmailPasswordPreBuiltUI])}
        </EmailVerificationComponentsOverrideProvider>
      );
    }
    return <SuperTokensWrapper>{/*Your app*/}</SuperTokensWrapper>;
  }
}