-
-
Notifications
You must be signed in to change notification settings - Fork 622
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
Version 1.0.1 broke ReScript bindings #572
Comments
Hi, thanks for your great work! I learned from the ReScript bindings that although jotai api is typescript oriented, its nature is dynamic JS, and not very strict type friendly. Well, I already struggle with
I'm afraid this is not possible. The purpose of
this sounds unfortunate. if there anything we could do without affecting JS and TS, please let us know. If you are familiar with TS, suggestions to |
I appreciate that but full credit should go to @gaku-sei for getting the first draft of working bindings out. Not sure I would have known where to even begin, fortunately I just have to keep the bindings in sync with the current version.
Fair enough, restricting to major versions is impractical in this case.
That's true it wasn't a breaking change, but it still is an API change. If a major version is unreasonable, could experimental changes be put into a @next tag? I understand your point that the update still fits the original signature but the function.length property still changed behind the scenes.
This error took me about a day to track down. It was a perfect storm where that get function deviating from the get function in a derived atom, and ReScript happens to curry against function.length.
I am thinking of drafting a Jotai-like library in ReScript to see how it would influence the API design. Especially since behavior like: const writableAtom = atom(
[],
(get, set, action) => {
const state = get(writableAtom);
switch (action.type) {
case 'append':
set(writableAtom, state.concat(action.payload));
break;
case 'replace':
set(writableAtom, action.payload);
break;
default:
// Nothing changes
break;
}
}
) Is not possible in ReScript. Perhaps the TS that ReScript generates will be an interesting reference? |
interesting. $ node
Welcome to Node.js v12.20.1.
Type ".help" for more information.
> function x(a) { return a }
undefined
> function y(a,b) { return a+(b||0) }
undefined
> function z(a,b=0) { return a+b }
undefined
> x.length
1
> y.length
2
> z.length
1 So, is it correct if we added the default value, it wouldn't have changed the |
I think that depends on how it's transpiled? In modern node, it is natively supported and unreported in the length. const writableAtom = atom(
[],
(get, set, action) => {
console.log("get length", get.length);
const state = get(writableAtom);
switch (action.type) {
case 'append':
set(writableAtom, state.concat(action.payload));
break;
case 'replace':
set(writableAtom, action.payload);
break;
default:
// Nothing changes
break;
}
}
) When using Jotai version 1.0.0 exactly, So perhaps either TS or a build setting in package.json is cheesing the optionality of unstable_promise? EDIT: If perhaps we can normalize the way optionality is supported then it should work just fine with the previous ReScript bindings! |
Looking a bit deeper into the transpiled JS it looks like the calling code is: var writeGetter = function writeGetter(a, unstable_promise) {
var aState = readAtomState(state, a);
if (aState.e) {
throw aState.e;
}
if (aState.p) {
if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {
if (unstable_promise) {
console.info('promise option in getter is an experimental feature.', a);
} else {
console.warn('Reading pending atom state in write operation. We throw a promise for now.', a);
}
}
if (unstable_promise) {
return aState.p.then(function () {
return writeGetter(a, unstable_promise);
});
}
throw aState.p;
}
if ('v' in aState) {
return aState.v;
}
if (typeof process === 'object' && process.env.NODE_ENV !== 'production') {
console.warn('[Bug] no value found while reading atom in write operation. This is probably a bug.', a);
}
throw new Error('no value found');
}; |
would you be able to use esm instead of cjs? cjs is rather for traditional browsers. |
Looked at const writeGetter = (a, unstable_promise) => {
const aState = readAtomState(state, a);
if (aState.e) {
throw aState.e;
}
if (aState.p) {
if (typeof process === "object" && process.env.NODE_ENV !== "production") {
if (unstable_promise) {
console.info("promise option in getter is an experimental feature.", a);
} else {
console.warn("Reading pending atom state in write operation. We throw a promise for now.", a);
}
}
if (unstable_promise) {
return aState.p.then(() => writeGetter(a, unstable_promise));
}
throw aState.p;
}
if ("v" in aState) {
return aState.v;
}
if (typeof process === "object" && process.env.NODE_ENV !== "production") {
console.warn("[Bug] no value found while reading atom in write operation. This is probably a bug.", a);
}
throw new Error("no value found");
}; |
Yeah. Here's the one #574. |
Spent the last 2 hours trying to get that to work. It works in my vanilla js example, but can't get Tried using native es module support but fails when working with jotai/esm/index.js imports. EDIT: Will keep at it and see if I can find the right combination of config + packages |
Turned out I had bindings in other files still pointing to regular jotai, replacing those with Tomorrow will try your fix in our actual project and see how it all comes together |
I'm doing some bindings for F#, still far from stable, but encountered a few issues related to the dyn nature of JS too. https://github.com/fc1943s/fluke/blob/master/src/Fluke.UI.Frontend/src/Bindings/Jotai.fs |
Confirmed it is working in our actual app without any tooling changes required. Reports get.length as 1 which means it's not auto-curried. Thanks for taking the time to listen and create that PR! |
That's good to hear. I will merge the PR. |
Working on ReScript bindings for Jotai, I didn't come up with these bindings but have been trying to help maintain them. https://github.com/eccentric-j/re-jotai/tree/stable. They're not complete, or perfect, but the core functionality is there and they pair quite well in so far. As of v1.0.1 though, the get function within a writable atom accepts an optional unstable_promise boolean which broke the bindings as ReScript was returning a function instead of the value of the dependent readable atom. I have a work around by defining a get wrapper that takes two arguments but it does require me to change all my existing writable atoms to call it. It's not ideal but sufficient to unblock progress.
ReScript bindings are likely far from anyone's priority with this project but it's worth recommending a process change to constrain future API changes to major version updates if possible to avoid issues like this. Please note overall I really like Jotai and very much appreciate the work required to make and maintain this library, I don't wish to curb innovation. Since Jotai hit 1.0.0 I am hoping we can find a compromise to avoid breaking dependent libs and bindings from minor version changes.
The text was updated successfully, but these errors were encountered: