Skip to content

Commit

Permalink
feat: remove hacks, make all buttons work, all the time
Browse files Browse the repository at this point in the history
Signed-off-by: Logan McAnsh <logan@mcan.sh>
  • Loading branch information
mcansh committed May 4, 2022
1 parent b4cf90c commit 298cd0e
Showing 1 changed file with 28 additions and 54 deletions.
82 changes: 28 additions & 54 deletions packages/remix-react/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -889,8 +889,6 @@ let Form = React.forwardRef<HTMLFormElement, FormProps>((props, ref) => {
Form.displayName = "Form";
export { Form };

type FormSubmitButton = HTMLButtonElement | HTMLInputElement;

interface FormImplProps extends FormProps {
fetchKey?: string;
}
Expand All @@ -913,70 +911,38 @@ let FormImpl = React.forwardRef<HTMLFormElement, FormImplProps>(
let formMethod: FormMethod =
method.toLowerCase() === "get" ? "get" : "post";
let formAction = useFormAction(action);
let formRef = React.useRef<HTMLFormElement>();
let ref = useComposedRefs(forwardedRef, formRef);

// When calling `submit` on the form element itself, we don't get data from
// the button that submitted the event. For example:
//
// <Form>
// <button name="something" value="whatever">Submit</button>
// </Form>
//
// formData.get("something") should be "whatever", but we don't get that
// unless we call submit on the clicked button itself.
//
// To figure out which button triggered the submit, we'll attach a click
// event listener to the form. The click event is always triggered before
// the submit event (even when submitting via keyboard when focused on
// another form field, yeeeeet) so we should have access to that button's
// data for use in the submit handler.
let clickedButtonRef = React.useRef<FormSubmitButton | null>(null);

React.useEffect(() => {
let form = formRef.current;
if (!form) return;

function handleClick(event: MouseEvent) {
if (!(event.target instanceof Element)) return;
let submitButton = event.target.closest<FormSubmitButton>(
"button,input[type=submit]"
);

if (
submitButton &&
submitButton.form === form &&
submitButton.type === "submit"
) {
clickedButtonRef.current = submitButton;
}
}

window.addEventListener("click", handleClick);
return () => {
window.removeEventListener("click", handleClick);
};
}, []);

return (
<form
ref={ref}
ref={forwardedRef}
method={formMethod}
action={formAction}
encType={encType}
onSubmit={
reloadDocument
? undefined
: (event) => {
console.log(event.nativeEvent);
onSubmit && onSubmit(event);
if (event.defaultPrevented) return;
event.preventDefault();

submit(clickedButtonRef.current || event.currentTarget, {
method,
replace,
});
clickedButtonRef.current = null;
let formData = new FormData(event.currentTarget);

let submitter = (event as unknown as HTMLSubmitEvent)
.nativeEvent.submitter;

if (submitter) {
let name = submitter.getAttribute("name");
let value = submitter.getAttribute("value");
if (name && value) {
formData.append(name, value);
}
}

console.log(Object.fromEntries(formData));

submit(formData, { method, replace });
}
}
{...props}
Expand All @@ -987,6 +953,12 @@ let FormImpl = React.forwardRef<HTMLFormElement, FormImplProps>(
FormImpl.displayName = "FormImpl";
export { FormImpl };

type HTMLSubmitEvent = React.BaseSyntheticEvent<
SubmitEvent,
Event,
HTMLFormElement
>;

/**
* Resolves a `<form action>` path relative to the current route.
*
Expand Down Expand Up @@ -1095,8 +1067,9 @@ export function useSubmitImpl(key?: string): SubmitFunction {
let formData: FormData;

if (isFormElement(target)) {
let submissionTrigger: FormSubmitButton = (options as any)
.submissionTrigger;
let submissionTrigger: HTMLButtonElement | HTMLInputElement = (
options as any
).submissionTrigger;

method =
options.method || target.getAttribute("method") || defaultMethod;
Expand All @@ -1106,6 +1079,7 @@ export function useSubmitImpl(key?: string): SubmitFunction {
options.encType || target.getAttribute("enctype") || defaultEncType;

formData = new FormData(target);
console.log(Object.fromEntries(formData));

if (submissionTrigger && submissionTrigger.name) {
formData.append(submissionTrigger.name, submissionTrigger.value);
Expand Down

0 comments on commit 298cd0e

Please sign in to comment.