bySabi / hookleton

globalize your React Hooks without fear using the Hookleton Pattern
MIT License
40 stars 1 forks source link

Support for Typescript. #2

Open namkaif opened 5 years ago

namkaif commented 5 years ago

Such a great package, currently having trouble though introducing it into a Typescript application.

bySabi commented 5 years ago

Hi @namkaif I am planning to move this project to Typescript. Any help is welcome

avkonst commented 5 years ago

@namkaif you might be interested in Hookstate. It is also based on hooks, allows to mix and match global and local states, and is written in typescript. Has got many plugins (validation, touch tracking, etc.) and incredible performance for complex nested data: see this and this demo.

@bySabi you might find the Hookstate interesting too. It addresses your concerns: it does not use context, HOC and is based on hooks. It does state usage tracking to avoid unnecessary rendering - but it is one of the main benefits - it allows to manage large form state and complex data (eg. trees) structures and many more worry-free.

bySabi commented 5 years ago

@avkonst thanks for take the time write here.

I've been looking at your proposal in hookstate but I can't quite understand how it works by looking at the documentation. I confess that reading typescript code gives me a headache :-) But in any case your library seems a complete and extensible solution for the optimal management of complex states.

Instead hookleton is transparent to the user's hook. The only thing it does is make sure to initialize and pass the user's hook output to all the components that use it but ensuring that the logic only runs in one place. It knows nothing about states but propagates the changes to all the components that use it.

His goals are:

Right now I am working on adding typescript support without losing the simple ones.

avkonst commented 5 years ago

It is plain simple. 2 functions essentially - create the state and use it. Here is the example: https://hookstate.netlify.com/global-getting-started You do not need the documentation until you want to know how it works in details. Check out other examples to pick up how various combinations of a couple of concepts cover most of the use cases.

Typescript is complex because the library supports complete and correct type inference for any possible type complexity of state data. It is not easy in generic case, but a user of a library does not really need to worry about typescript definitions, IDE intellisense will do correct automatic completion - it is the point of type inference in addition to compile time type checking.

Good luck anyway!

On Thu, Oct 24, 2019 at 8:20 PM bySabi Files notifications@github.com wrote:

@avkonst https://github.com/avkonst thanks for take the time write here.

I've been looking at your proposal in hookstate but I can't quite understand how it works by looking at the documentation. I confess that reading typescript code gives me a headache :-) But in any case your library seems a complete and extensible solution for the optimal management of complex states.

Instead hookleton is transparent to the user's hook. The only thing it does is make sure to initialize and pass the user's hook output to all the components that use it but ensuring that the logic only runs in one place. It knows nothing about states but propagates the changes to all the components that use it.

His goals are:

  • Share the output of a hook (logic, state, updaters, ...) among several components with the simplest possible API.
  • Efficient, without unnecessary rendering AKA avoid Context.
  • State agnostic. Let everything React do it
  • Again, be the simplest API out there.

Right now I am working on adding typescript support without losing the simple ones.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/bySabi/hookleton/issues/2?email_source=notifications&email_token=AA6JSVJJZJ2U4IWGIPQSXBTQQFEFJA5CNFSM4JBPDAK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOECD7VTY#issuecomment-545782479, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA6JSVOV4FPZE725B2O34NDQQFEFJANCNFSM4JBPDAKQ .

bySabi commented 5 years ago

Ah! thanks for the last example. Now is more clear to me. Good job!

Thanks.

mh-alahdadian commented 4 years ago

well done , I liked your library very much any update on converting to typescript? needs any help?

bySabi commented 4 years ago

Hi @MHA15 I am very happy that you like this project.

My last attempt at creating a type definition for Hookleton failed. The difficulty is that Hookleton treats the user's hooks in the most opaque way possible. Ideally when you create a hookleton such as:

// useCounter is a useState but global
const useCounter = createHook (useState);

useCounter should have the same type signature as useState but I could not implement it. I probably don't have the expertise to do it. :-)

It would be great if someone could contribute the solution to this or another solution that allows us to have a few minimal types.

Do you dare with this?

bySabi commented 4 years ago

As I said before, the createHook function receives, as a first parameter, a function followed by a variable number of parameters. createHook does not impose any restrictions on the types of the parameters because it acts simply as a wrapper of the Hook provided by the user. The wrapper is completely opaque to the structure and the types of input and output of the function provided. Something like that ...

   const result = hook.apply(null, initial);

A possible type definition could be something like this:

   function createHook<R>(hook: () => R, ... initial ?: any []): R

The type signature should be inferred depending on the first parameter that is passed to createHook

If I want to create a hookleton from useState, that has the following types:

useState <S> (initialState: S | (() => S)): [S, Dispatch <SetStateAction <S>>]

The result should be this:

const useStateGlobal = createHook (useState, 0); // useStateGlobal (): [number, Dispatch <SetStateAction <number>>]

The initialState parameter of useState can have any value included undefined that matches the ... initial ?: any [] above.

On the other hand, if I want to globalize a hook like useReducer that needs initialization parameters, the ...initial parameter of createHook is required.

I confess that I do not have the necessary knowledge of Typescript to extract the types from the parameters or to know if this can be done or what the compromise solution would be.

I think we need a champion of Typescript that brings us some light here. I only know one, @dragomirtitian who has helped me other times in StackOverflow.

I hope you have time to take a look at this thread @dragomirtitian