Hello, I discover Zustand recently, and I really like the API. Unfortunatly i can’t make it work due to Rescript typing rules. Here is some code in order to help you understand.
First the bindings:
module type StoreConfig = {
type state
}
module MakeStore = (Config: StoreConfig) => {
type set = (. Config.state => Config.state) => unit
type selector<'a> = Config.state => 'a
type useStore<'a> = selector<'a> => 'a
@module("zustand")
external create: (set => Config.state) => useStore<'a> = "create"
}
And some code to test, and see the problem:
module AppStore = {
type state = {
counter: int,
increment: unit => unit,
decrement: unit => unit,
}
}
module SomeStore = Zustand.MakeStore(AppStore)
let useStore = SomeStore.create(set => {
counter: 0,
increment: _ => set(.state => {...state, counter: state.counter + 1}),
decrement: _ => set(.state => {...state, counter: state.counter - 1}),
})
let someCounter = useStore(state => state.counter)
let decrement = useStore(state => state.decrement)
I you install zustand npm i zustand --save and you add those 2 files to your project, you’ll see that rescript doesn’t like the second useStore because the first return an int, and the second return a function.
Does anybody knows how to use the function useStore with different types ? (I did some bindings for redux toolkit, and since i’m using an external function to get some data from the store, that way, it works…)
@mouton thank for your answer, but if you look closely, the problem is different for Zustand. I already did some bindings for Redux Toolkit, and they look like yours, but in my case, i need to retrieve the return value of the function useStore.
As i understand, if useStore was an external bindings, it would work, but since it is not, it doesn’t work.
I think this is the value restriction at work. When you apply a function to its argument, the compiler gives the result value a single concrete type, and that type can’t change from one call to the next. But if you show the compiler that you’re actually creating a new function, the new function can be called with its argument and can return values of different types from one call to the next. Fixed code
Thank for your answer, but with your solution, i create a new store everytime i use the useStore function. Which is not what I’m trying to do. I need to call only once the create function, and then i can use the resulting store by passing a selector in order to get some value / actions / etc.
It seems that i cannot use Zustand in Rescript due to the type system.
There’s another option. Since useStore needs a function which returns the same type each time, just wrap up the returned values in a variant type which gives them all the same type. Link
Admittedly not as convenient, but it should get the job done.
I saw your solution, and I don’t think that it would be scalable enough. Thx for the tries
I decided to go with rematch, since it seems impossible to produce good bindings for zustand in Rescript.
Maybe in the future, it will be possible
Yes, I’m using Zustand with React, and no, i don’t want to use React.useReducer ou React.useState, since i need a store for my app. And we should not use react state with context to manage app state. Because on every context change, all the component would re-render, so it’s not opti at all.
That’s why we use tools, like redux and co
I also use clean architecture on all my front-end project, in order to switch the ui easily (i’m using the same application logic on my web app and my native app, with react native for example).
So when i switch ui, i only have to code the new components.