Skip to content

Instantly share code, notes, and snippets.

@siassaj
Last active July 15, 2020 07:38
Show Gist options
  • Save siassaj/2659e36f79402cdb25f415f8bdf99aac to your computer and use it in GitHub Desktop.
Save siassaj/2659e36f79402cdb25f415f8bdf99aac to your computer and use it in GitHub Desktop.
import React, {
useEffect,
useState,
useContext,
useReducer,
createContext,
PropsWithChildren,
Context,
} from "react";
type FormData<T extends Record<string, any>> = {
values: T;
errors: Record<keyof T, Array<string> | undefined>;
};
type Props<T extends Record<string, any>> = PropsWithChildren<{
children: (
context: Context<
[FormData<T>, React.Dispatch<(state: FormData<T>) => unknown>]
>
) => React.ReactElement;
initialData: FormData<T>;
}>;
export default function FormControl<T>({ children, initialData }: Props<T>) {
const [state, setState] = useState(initialData);
const [Context, setContext] = useState<
Context<[FormData<T>, typeof setState]> | undefined
>(undefined);
useEffect(() => {
setContext(createContext([state, setState]));
}, [setContext]);
return Context ? (
<Context.Provider value={[state, setState]}>
{children(Context)}
</Context.Provider>
) : (
<></>
);
}
type BaseProps<T extends Record<string, any>> = {
context: Context<FormData<T>>;
key: keyof T;
};
export function BaseInput<T extends Record<string, any>>({
context,
key,
}: BaseProps<T>) {
const formData = useContext(context);
const value = formData.values[key];
const errors: Array<string> = formData.errors[key];
const hasErrors = errors.length !== 0;
const className = hasErrors ? "hasError" : "happyAF";
return (
<div>
<label>{key}</label>
<input className={className} value={value} />
{hasErrors && (
<span className="dangerwords">
{errors.map(e => (
<>
{e}
<br />
</>
))}
</span>
)}
</div>
);
}
function Main() {
return (
<FormControl initialData={{ values: { firstName: "smashy" }, errors: { firstName: ["silly name"] } }}>
(context) => (
<>
<BaseInput context={context} key="firstName" />
</>
)
</FormControl>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment