简体   繁体   中英

TypeScript Reusable Form with React Bootstrap

I'm following this post to learn react and typescript forms. There is a reusable form with React Bootstrap explained which I like to implement. I have tried to do so by writing the user form like below. But I' am getting

TS7031: Binding element 'cancel' implicitly has an 'any' type

and I don't know how to use it once i have solved this error. If I want for example to implement a sign-in form and a log-in form how do i refer to the user form below

import React from 'react';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import styled from 'styled-components';

const UserForm =
    ({
        cancel,
        errors,
        submit,
        submitButtonText,
        elements,
        passwordErrors
    }) => {

    function handleSubmit(event) {
        event.preventDefault();
        submit();
    }

    function handleCancel(event) {
        event.preventDefault();
        cancel();
    }

    return (
        <React.Fragment>
            <ErrorsDisplay errors={errors} passwordErrors={passwordErrors} />
            <Form onSubmit={handleSubmit}>
                {elements()}
                <Button className="mr-1" variant="primary" type="submit">{submitButtonText}</Button>
                <Button className="mr-1" variant="secondary" onClick={handleCancel}>Cancel</Button>
            </Form>
        </React.Fragment>
    );
 };

function ErrorsDisplay({ errors, passwordErrors}) {
    let errorDisplay = null;
    if (errors.length) {
        errorDisplay = (
            <React.Fragment>
                <ValidiationLabel>Errors:</ValidiationLabel>
                <ValidiationUl>
                    {errors.map((error, i) => (
                        <li key={i}>{error}</li>
                    ))}
                </ValidiationUl>
            </React.Fragment>
        );
    } else if (!passwordErrors) {
        errorDisplay = (
            <React.Fragment>
                <ValidiationLabel>Errors:</ValidiationLabel>
                <ValidiationUl>{<li>Passwords must match</li>}</ValidiationUl>
            </React.Fragment>
        );
    }
    return errorDisplay;
}

const ValidiationUl = styled.div`
    color: red;
    padding: 15px 0 40px 10px;
  `;
const ValidiationLabel = styled.h2`
    color: #0069c0;
    font-size: 28px;
  `;
export default UserForm;

First, assuming that you are using typescript project as you said (.tsx file extension), you need to type the parameters for UserForm:

// This is just an example, not necessary needs to be this exactly types for the parameters
interface UserFormProps {
  cancel(): void; // cancel is a function that returns nothing
  submit(): void;
  errors: string[]; // errors its an array of strings
  passwordErrors: boolean;
  submitButtonText: string;
  elements(): ReactNode; // elements its a funtion that returns react nodes

}

// Here you are destructuring the object parameter of UserForm function.
// You telling it that its an UserFormProps Type Object on ": UserFormProps"
const UserForm = ({
  cancel,
  submit,
  elements,
  errors,
  submitButtonText,
  passwordErrors,
}: UserFormProps) => { .....

and for ErrorsDisplay function:

interface ErrorsProps {
  errors: string[];
  passwordErrors: boolean;
}

function ErrorsDisplay({ errors, passwordErrors }: ErrorsProps) {...

For your handle functions, you need to specify the type of event:

// You are saying the handleSubmit function receives an FormEvent from a HTML Form Element
function handleSubmit(event: React.FormEvent<HTMLFormElement>) { ....

// You are saying the handleCancel function receives an MouseEvent from a HTML Button Element
function handleCancel(event: React.MouseEvent<HTMLButtonElement>) { ....

After doing this, you can use your UserForm anywhere, for example your sign-in page / log-in page.

You just need to import it:

import React from "react";
import Form from "react-bootstrap/Form";
// here you need to inform the path according to your project
import UserForm from "./UserForms";

const SignIn = () => {
  return (
    <UserForm
      // I'm setting the values ​​hardcoded just as example
      cancel={() => {console.log('cancel')}}
      submit={() => {console.log('submit')}}
      errors={[]}
      passwordErrors={false}
      submitButtonText="test"
      elements={() => (
        <>
          <Form.Group controlId="ControlId">
            <Form.Control
              type="email"
              name="email"
              value={"email@c.com.br"}
              placeholder={"email"}
            ></Form.Control>
            <Form.Control
              type="password"
              name="password"
              value={"password"}
              placeholder={"password"}
            ></Form.Control>
          </Form.Group>
        </>
      )}
    ></UserForm>
  );
};

export default SignIn;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM