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

Data loading and writing bindings #1

Open
tom-sherman opened this issue Dec 20, 2021 · 2 comments
Open

Data loading and writing bindings #1

tom-sherman opened this issue Dec 20, 2021 · 2 comments

Comments

@tom-sherman
Copy link
Owner

@tom-sherman
Copy link
Owner Author

We have a useLoaderData hook binding but it currently returns a 'a which isn't type safe. We can solve this with a functor

module Remix = {
  @module("remix") external useLoaderData: unit => 'a = "useLoaderData"

  module type Loadable = {
    type t
    // TODO: loaderParams definition
    type loaderParams = {..}
    let loader: loaderParams => Promise.t<t>
  }

  module Loader = (Loadable: Loadable) => {
    include Loadable

    let use = (): Loadable.t => useLoaderData()
  }
}

And then in a route eg. app/routes/users.res:

module UsersLoader = Remix.Loader({
  type t = array<User.t>

  let loader = _ => Api.getUsers()
})

let loader = UsersLoader.loader

@react.component
let default = () => {
  let users = UsersLoader.use() // => array<User.t>
}

@tom-sherman tom-sherman transferred this issue from tom-sherman/rescript-remix-template Jan 8, 2022
@tom-sherman
Copy link
Owner Author

tom-sherman commented Jan 11, 2022

I have a WIP PR for how this could look in #19 but I'm not sure about it... Mainly because it doesn't guarantee type safety, you can call the wrong Loader.use() in the wrong route and your app will explode.

It also comes with some clunkiness in terms of autocomplete and IDE hints. I think also there's no way for the t to be a record without either hoisting the type definition out into the containing scope or naming the anonymous module, neither is ideal eg.

module Data = {
  type t = {hi: int}

  let loader = _ => Js.Promise.resolve({hi: 5})
}

module Loader = Remix.Loader(Data)

let x = Loader.use()
let y = x.Data.hi

Or

type data = {hi: int}

module Loader = Remix.Loader({
  type t = data

  let loader = _ => Js.Promise.resolve({hi: 5})
})

let x = Loader.use()
let y = x.hi

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant