cassiozen / useStateMachine

The <1 kb state machine hook for React
MIT License
2.38k stars 47 forks source link

Shorthand syntax for updating context #19

Closed cassiozen closed 2 years ago

cassiozen commented 3 years ago

Right now, the context updater function behaves almost like a reducer: it gives you the current context and you have to immutably return the next context.

It would be nice if it merging syntax like the old React's component-based setState.

chavda-bhavik commented 3 years ago

Hey @cassiozen, I somewhat got your point, we want to work on this syntax https://github.com/cassiozen/useStateMachine/blob/main/examples/fetch/index.tsx#L37, right? Can you give an example for old React's component-based setState?

icyJoseph commented 3 years ago

@chavda-bhavik I think the idea is to expect a partial update return from the updater and internally merge that with the current reducer context:

These lines https://github.com/cassiozen/useStateMachine/blob/main/src/index.tsx#L65 :

  const nextContext = event.updater(state.context);
  if (config.verbose) log('Context update from %o to %o', state.context, nextContext);

Would be:

  const partialContextUpdate = event.updater(state.context);
  const nextContext = {...state.context, ...partialContextUpdate};
  if (config.verbose) log('Context update from %o to %o', state.context, nextContext);

I think the object merge is safe from prototype pollution by the TS compiler, and it is transpiled to Object.assign, which is pretty fast.

event.updater would return a Partial<Context> and we may need to assert (or cast, really bad stuff) the merging of state.context with partialContextUpdate as a full Context update. Though, my instinct tells me that the compiler is going to infer that nextContent is a full Context.

A little snippet of what I mean with partial + full merge.

type Tree = {
    leaves: string[];
    nodes:string[];
}

const state:Tree = {leaves:[], nodes:[]};

const partial: Partial<Tree> = {leaves:[]};

function merge(partial:Partial<Tree>, full: Tree): Tree {
    return {...full, ...partial};
}

const next = merge(partial, state) // Tree

Or maybe I am way off :)

cassiozen commented 3 years ago

You're not off at all, @icyJoseph, thanks for the detailed explanation!