Skip to content

Instantly share code, notes, and snippets.

@jtmthf
Created November 4, 2021 19:15
Show Gist options
  • Save jtmthf/3e26f7d419f5295c44084fe8a9782312 to your computer and use it in GitHub Desktop.
Save jtmthf/3e26f7d419f5295c44084fe8a9782312 to your computer and use it in GitHub Desktop.
import { useState, useEffect, Dispatch, SetStateAction } from 'react';
import { createContainer } from 'react-tracked';
import { ActionFunction, EventObject, MachineOptions } from 'xstate';
function createUseRegister<V extends object, T>(key: keyof V, useUpdate: () => Dispatch<SetStateAction<V>>) {
return function useRegister(name: string, value: T) {
const setState = useUpdate();
useEffect(() => {
setState((options) => ({
...options,
[key]: { ...options[key], [name]: value}
}));
return () => {
setState((obj) => {
const {[key]: property, ...options} = obj;
const { [name]: _, ...rest } = property ?? {} as Record<string, any>;
return {
...options,
[key]: rest
} as V;
});
}
}, [name, value]);
}
}
export function createMachineOptionsContext<
TContext,
TEvent extends EventObject,
>() {
function useMachineOptions() {
return useState<Partial<MachineOptions<TContext, TEvent>>>({});
}
const { Provider, useTrackedState, useUpdate } =
createContainer(useMachineOptions);
const useAction = createUseRegister<MachineOptions<TContext, TEvent>, ActionFunction<TContext, TEvent>>('actions', useUpdate as () => Dispatch<SetStateAction<MachineOptions<TContext, TEvent>>>);
return {
Provider,
useMachineOptions: useTrackedState,
useAction,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment