zilch / type-route

The flexible, type safe routing library.
https://type-route.zilch.dev
MIT License
426 stars 14 forks source link

feedback - Better way of rendering routes need to exist #113

Closed brunofin closed 1 year ago

brunofin commented 2 years ago

Hi, I went through all your docs and examples and I find this library has come really a long way and has a lot of potential. It seems to be prepared for every situation modern React can through at it. Despite all that, I am still having issues with the rendering philosophy in this lib.

<>
      {route.name === "home" && <HomePage/>}
      {route.name === "foo" && <FooPage/>}
      {route.name === "bar" && <BarPage/>}
      {route.name === false && <NotFoundPage/>}
    </>

I find this to be too much verbose and as a simple example, I could get over it. But when routes get more complex and we start having nested routes, the real issue arises and verbosely comparing groups and then routes in each element simply feels wrong in my opinion.

I think this area needs a little more improvement for the library to reach its full potential.

One more thing I feel it could be improved is on how route is prop-drilled into subsequent components down from the top-level App component. I think this might just be a lack of a better example though? Probably the hook const route = useRoute(); could be called in each component instead of sending route down via props and it would also work?

bradenhs commented 2 years ago

Thanks for the feedback! You're free to call useRoute() in each component if you'd like and it works for you. You may run into the issue, however, of needing to narrow the type with checks like route.name === "foo" anyhow because different routes will likely have different params available on them. You won't be able to access those specific params unless you first check which route you're dealing with. The concept here isn't any different than dealing with normal objects in TypeScript:

interface Foo {
  name: "foo";
  foo: boolean;
}

interface Bar {
  name: "bar";
  bar: boolean;
}

type FooBar = Foo | Bar;

const someVar: FooBar = ...

someVar.bar; // errors b/c you don't know if someVar is Foo or Bar here

if (someVar.name === "bar") {
  someBar.bar; // ok b/c you narrowed the type first
}

This is the same sort of pattern that Type Route encourages folks to follow b/c it allows you to access stuff in a type safe way - which is the main goal of the library. The idea is to rely on the compiler more so you have fewer bugs at runtime.

I'm very open to different ways of accomplishing this provided users get the same level of type safety. I can put some thought into it. Feel free to tinker with it yourself. Would love to see any suggestions!