That is, are all jQuery functionality available easily when using ReScript? I’m working on a legacy application and might need to interact some with older HTML and JS.
JQuery api doesn’t have anything that would be impossible to interop with. Usually I could have problems when a lib uses generators, proxies, or require doing some dirty mutations with unstructured objects. That’s not the case for JQuery
Thanks for your answer! Is there a link with examples?
You can create a JQuery.res
file and add in bindings as you come across features you use.
For example
type t
@module external jQuery: string => t = "jquery"
@send external append: (t, string) => t = "append"
@send external appendElement: (t, t) => t = "append"
@send external appendElementMany: (t, t[]) => t = "append"
@send external addClass: (t, string) => t = "addClass"
@send external removeClass: (t, string) => t = "removeClass"
@send external text: (t, string) => t = "text"
And then to use would look like
open JQuery
jQuery("#item")
->append("<p>")
->addClass("some-class")
->text("Hello World!")
That’s great!, buuut no one did that already? Maybe jQuery is not commonly used in ReScript projects?
JQuery isn’t really common in general outside of legacy projects. You can do most of jQuery’s useful features natively in the browser now, and people tend to prefer component based development these days
After trying both bs-fetch and react-query without success, maybe you can help me with writing the types for jQuery.get() and .post() for JSON…?
Edit, actually got both bs-fetch and react-query to work now, by tinkering with ->
and |>
. Examples in source are not correct.
So for me personally, I’ve found that most bindings are easy enough to just do yourself real quick, and as the only consumer you can simplify the api since you don’t need to cover “every case”
For instance, for fetch, I just created a loosely typed fetch binding and then added on helper methods for get, post, etc. It looks something like this:
module Fetch = {
exception Unexpected_Error
exception Not_Found
type response<'a> = {status: int}
let stringify = obj => Js.Json.stringifyAny(obj)->O.orElse("")
@send external json: response<'a> => 'a = "json"
@scope("window") @val external fetch: (string, {..}) => Promise.t<response<'a>> = "fetch"
let mapStatus = response =>
switch response.status {
| 200 => json(response)
| 404 => raise(Not_Found)
| _ => raise(Unexpected_Error)
}
let get = url =>
fetch(url, {"method": "GET"})
-> Promise.map(mapStatus)
let post = (url, body) =>
fetch(url, {
"method": "POST",
"body": stringify(body),
"headers": {
"Content-Type": "application/json",
},
})-> Promise.map(mapStatus)
}
And then I have a module for my actual API calls
module Game = {
type responseWithId = {gameId: string}
external unsafeCastGameId: Promise.t<'a> => Promise.t<responseWithId> = "%identity"
let create = (userId: string, courseId: string) =>
Fetch.post(endpoint("/games"), {
"userId": userId,
"courseId": courseId,
},)->unsafeCastGameId
let join = (userId: string, gameId: string) =>
Fetch.post(endpoint(`/games/${gameId}/join`), {"userId": userId})->unsafeCastGameId
let fetch = gameId =>
Fetch.get(endpoint(`/games/${gameId}`))->unsafeCastGame
let scores = gameId =>
Fetch.get(endpoint(`/games/${gameId}/scores`))->unsafeCastScores
let addScore = (~gameId: string, ~userId: string, ~label: string) => {
Fetch.post(endpoint(`/games/${gameId}/scores`), {
"userId": userId,
"label": label,
})
}
}
I did something similar for react-query, and in the end my query looks like this
let useCurrentGame = () => {
let (roomId, _) = useRoomId()
let roomId = O.orElse(roomId, "DOESNT_EXIST")
RQ.useQuery(
RQ.key(["games", roomId]),
() => Api.Game.fetch(roomId)
)
}