Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

defineRoute #11596

Closed
wants to merge 8 commits into from
Closed

defineRoute #11596

wants to merge 8 commits into from

Conversation

pcattori
Copy link
Contributor

@pcattori pcattori commented May 28, 2024

TODO

  • clientLoader -> data inference
  • actionData inference
  • compile-time checks for defineRoute used elsewhere?
  • fix TS infinite error when only params are provided
  • readonly serializable
  • apploadcontext interface
  • additional props: handle, HydrateFallback, shouldRevalidate, Layout, meta, links
  • vite child compiler for mdx? or not?
  • Root layout
  • HMR
  • tests
  • Changeset/docs

Copy link

changeset-bot bot commented May 28, 2024

⚠️ No Changeset found

Latest commit: 1a3dcdc

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@remorses
Copy link

remorses commented Jun 4, 2024

I don’t really like the $ at the end of the name, users will see it and just think it’s weird. It won’t send the message “this function must be statically analyzable”.

Instead just print an error from vite if the call is not statically analyzable.

@pcattori
Copy link
Contributor Author

pcattori commented Jun 4, 2024

I don’t really like the $ at the end of the name, users will see it and just think it’s weird. It won’t send the message “this function must be statically analyzable”.

Instead just print an error from vite if the call is not statically analyzable.

I'm actually thinking of backing out the $ anyway since originally defineRoute$ was a macro that could be called anywhere, but we're still sticking with route modules for the moment (no way to define multiple routes in a single module, maybe we'll allow this later but for now no). So really all of the AST transforms will happen on export default value independent of whether defineRoute$ was used or not. So likely this'll end up as defineRoute all the same.

@pcattori pcattori changed the title defineRoute$ defineRoute Jun 4, 2024
@willhoney7
Copy link

Apologies if there's a discussion open for this but I couldn't find it.

Is there going to be support for importing and using the component that's defined in the defineRoute$ anywhere in the app?

// widget/route.tsx
export const defineRoute$( { .... });

// another route/file
import { route.Component as MyWidget } from 'widget/route.tsx';

export default function() {
  return <div><MyWidget /></div>
}

This is the premise of the full-stack components using resource routes that Kent talked about: https://www.epicweb.dev/full-stack-components. It kinda works right now... but it's really clunky and requires hard-coding the action URL or manually calling fetcher.load for loader data.

Being able to import and use these components anywhere in the app (instead of just as routes) would be such a huge game changer for interaction heavy apps. This has been the missing piece in remix for us.

@pcattori
Copy link
Contributor Author

pcattori commented Jun 4, 2024

@willhoney7 you could access the Component of a route that way, but its just the React component, not the loader/action/etc. for that route. So including it in another route like you've shown would likely cause the Component to ask for data that doesn't exist in that new route.

What you are asking for is composability of data fetching and UI anywhere in your app. We had some designs for how to do this a couple years ago, but then RSC came out and changed the foundations of how this could work in React. So for the sort of composability you're asking for, the best bet is to wait for our RSC support to be stabilized.

// loader -> data for component
// loader -> serverLoader for clientLoader -> data for component
// TODO: clientLoader and all the other route module export APIs (meta, handle, ErrorBoundary, etc.)
export const defineRoute$ = <

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First of all, thank you for your work on improving support for typed routes! 🎉

Do you have plans to support typing for searchParams in the future? Sorry if this was mentioned already and I missed it!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not in the immediate future (RRv7.0 initial release) but the API is flexible to accommodate that later without breaking changes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, for the clarification 🐱. Awesome work!


type MaybePromise<T> = T | Promise<T>;

type Serializable =
Copy link

@hiendaovinh hiendaovinh Jun 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could we make this Serializable ?

type Foo = {
  k: readonly string[]
}
const foo: Foo = {k: ['v']}
const bar: Serializable = foo
Type 'Foo' is not assignable to type 'Serializable'.
  Type 'Foo' is not assignable to type '{ [key: string]: Serializable; [key: number]: Serializable; [key: symbol]: Serializable; }'.
    Property 'k' is incompatible with index signature.
      Type 'readonly string[]' is not assignable to type 'Serializable'.
        Type 'readonly string[]' is not assignable to type '{ [key: string]: Serializable; [key: number]: Serializable; [key: symbol]: Serializable; }'.
          Index signature for type 'string' is missing in type 'readonly string[]'.ts(2322)

Without readonly, it works fine.

Sorry, this supposed to be about SingleFetch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea that's a bug. We'll fix it.

loader?: L;
action?: A;
Component?: Component<NoInfer<P>, NoInfer<L>>;
}) => route;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note to self: return never?

@depsimon
Copy link

depsimon commented Jun 7, 2024

Would be cool if this new way of defining routes would allow for easy route duplications somehow.

I'd love to be able to do something like this (current API):

const customRoutes = defineRoutes((route) => {
  route("/", "routes/_app.tsx"); // Go to /issues and you see all issues you have access to
  route("/organization/:organizationId", "routes/_app.tsx"); // Go to /organization/:organizationId/issues and you see all issues for the organization
  route("/organization/:organizationId/project/:projectId", "routes/_app.tsx"); // Go to /organization/:organizationId/project/:projectId/issues and you see all issues for the specific project of the organization
});

This currently throws an error:

Error: Unable to define routes with duplicate route id: "routes/_app"

If we specify unique IDs it prevents the error, but doesn't register the new routes.

Anyway, it'd be great if this scenario was possible easily without having to play with redirections & duplications of real route files.

@pcattori
Copy link
Contributor Author

pcattori commented Jun 7, 2024

I appreciate all the excitement around this feature! But I want to keep this PR focused on the current implementation. Any feature requests should instead be made as a discussion in this repo, thanks 🙏

@remix-run remix-run locked as off-topic and limited conversation to collaborators Jun 7, 2024
@brophdawg11 brophdawg11 added the v7 label Jun 14, 2024
@pcattori
Copy link
Contributor Author

pcattori commented Jul 1, 2024

I'm landing this feature incrementally in a bunch of smaller PRs so that we can make sure we don't break anything along the way.

@pcattori pcattori closed this Jul 1, 2024
@pcattori pcattori deleted the define-route branch July 1, 2024 22:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants