3

I want to post whatever values are in the form to the API, im using useRef to get the form like this...

  const formElement = useRef<HTMLFormElement>(null);

Submit function

  const submit = async (event: React.FormEvent) => {
    event.preventDefault();
    const body = new URLSearchParams(new FormData(formElement.current)); // <=== error
    const response = await fetch(baseUrl, { body, method: 'post'});
  };

and the form

<form onSubmit={submit} ref={formElement}>
   <input type='text' id='test' value='testValue'/>
</form>

The error I get is in the console, then it fails to compile

Argument of type 'HTMLFormElement | null' is not assignable to parameter of type 'HTMLFormElement | undefined'. Type 'null' is not assignable to type 'HTMLFormElement | undefined'.ts(2345)

The entire component is here...

     <Poster
        method='post'
        baseUrl='https://api.funge.it/join'
        auth={false}
        keys='email, fullName, password, username'
      />


import React, { useContext, useRef, useState } from 'react';
import { BEARER_TOKEN, Dispatch, Global } from '../globalState';

interface PropsInterface {
  auth: boolean;
  baseUrl: string;
  keys: string;
  method: string;
}

const Poster: React.FC<PropsInterface> = (props: PropsInterface) => {
  const { global } = useContext(Global);
  const { dispatch } = useContext(Dispatch);

  const [state, setState] = useState({
    auth: props.auth,
    baseUrl: props.baseUrl,
    keys: props.keys.split(','),
    method: props.method,
  });
  const { auth, baseUrl, keys, method } = state;
  const { bearer } = global;
  const baseUrlRef = useRef<HTMLInputElement>(null);
  // const formElement = useRef<HTMLFormElement>(null);
  // const formElement = useRef<HTMLFormElement | null>();
  // const formElement = useRef<HTMLFormElement | undefined>();
  const formElement = React.useRef() as React.MutableRefObject<HTMLFormElement>;

  const submit = async (event: React.FormEvent) => {
    event.preventDefault();
    setState((prev) => ({ ...prev, loading: true }));
    const body = new URLSearchParams(new FormData(formElement.current));
    const response = await fetch(baseUrl, { body, method });
    const content = await response.json();
    setState((prev) => ({ ...prev, response, loading: false }));
    if (response.status === 200 && content.jwtToken) {
      dispatch({ type: BEARER_TOKEN, value: content.jwtToken });
    }
  };
  const copy = (event: React.MouseEvent) => {
    event.preventDefault();
    if (baseUrlRef.current) baseUrlRef.current.select();
    document.execCommand('copy');
    const button = event.target as HTMLButtonElement;
    button.focus();
  };

  return (
    <form className='poster' onSubmit={submit} ref={formElement}>
      <div className='poster--where'>
        <div className='poster--where-container-method'>
          <div className='poster--method'>{method}</div>
          <input type='text' value={baseUrl} ref={baseUrlRef} readOnly className='poster--url' />
        </div>
        <div className='poster--where-container-actions'>
          <button className='poster--send'>Send</button>
          <button className='poster--copy' onClick={copy}>
            Copy
          </button>
        </div>
      </div>
      {auth && (
        <div className='poster--auth'>
          <div className='poster--auth-type'>Bearer Token</div>
          <input type='text' value={bearer} readOnly className='poster--url' />
        </div>
      )}
      {keys.map((item, index) => {
        return (
          <div className='poster--keys-values'>
            <div className='poster--key-title'>{item}:</div>
            <input
              type='text'
              id={item}
              key={index}
              className='poster--value-title'
            />
          </div>
        );
      })}
    </form>
  );
};

export { Poster };

UPDATE Natarich J I now get this error in the ref on the input

I so wish it did but i now get an error in the ref part of the input
`Type 'MutableRefObject<HTMLFormElement | undefined>' is not assignable to type 'string | ((instance: HTMLFormElement | null) => void) | RefObject<HTMLFormElement> | null | undefined'.
  Type 'MutableRefObject<HTMLFormElement | undefined>' is not assignable to type 'RefObject<HTMLFormElement>'.
    Types of property 'current' are incompatible.
      Type 'HTMLFormElement | undefined' is not assignable to type 'HTMLFormElement | null'.
        Type 'undefined' is not assignable to type 'HTMLFormElement | null'.ts(2322)
index.d.ts(106, 9): The expected type comes from property 'ref' which is declared here on type 'DetailedHTMLProps<FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>'`
4
  • stackoverflow.com/a/41198567/982311 Commented Jan 30, 2020 at 10:23
  • Is it not possible with useRef? Commented Jan 30, 2020 at 10:26
  • Output when console logging formElement.current Commented Jan 30, 2020 at 10:28
  • the TypeScript won't even compile, I can't get an output unfortunately Commented Jan 30, 2020 at 10:31

1 Answer 1

1

The error log basically says there was a type mismatch. It is likely because you assigned null to formElement.

Since FormData only receives data of type either HTMLFormElement or undefined. But you assigned null to formElement which indicates formElement is also of type null, which basically means the following:

typeof formElement                 ===> <HTMLFormElement> || null
typeof data_that_FormData_receives ===> <HTMLFormElement> || undefined

You see there is a mismatch. So probably the solution is

# I forgot whether should be '|' or '||', play around with it...

const formElement = useRef<HTMLFormElement || undefined>(); 

Tell me if it works


Update:

Also you should not need new URLSearchParams(), just do this instead

const body = new FormData(formElement.current)
Sign up to request clarification or add additional context in comments.

9 Comments

it was single pipe | but I get a new error ... Argument of type 'FormData' is not assignable to parameter of type 'string | string[][] | Record<string, string> | URLSearchParams | undefined'. Property 'sort' is missing in type 'FormData' but required in type 'URLSearchParams'.ts(2345) lib.dom.d.ts(16068, 5): 'sort' is declared here.
@Bill This is because the formdata you get from new FormData(data) is of type FormData, which is not a valid type for being the parameters of URLSearchParams.
maybe new URLSearchParams() is not needed? would just const body = new FormData(formElement.current); work?
@Bill Since you will pass it as the body of a post request, then yes you don't need to new URLSearchParams(), just use new FormData() shall work
@Bill is duplicating your errors. Please wait for a while
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.