Search code examples
javascriptreactjsformsmaterial-uireact-forms

Form is not submitting in react js


I have a form that should print the data in console but unfortunately I'm not able to. I want to print data to the console when a form is submitted. The form is not submitting don't know why. I have the code below. I would be very grateful if you could decide.

import { Button, Grid, Paper, TextField } from "@mui/material";
import React from "react";
import { useForm } from "react-hook-form";

export default function Page2(props) {
    const { handleSubmit } = useForm();

    const handelInputChange = (e) => {
        const { name, value } = e.target;
        console.log(name, value);
    };

    const handleData = (data) => {
        console.log("data");
    };

    return (
        <>
            <Paper
                style={{ margin: "10px auto", textAlign: "center" }}
                elevation={24}  >
                <h1 style={{ textAlign: "center" }}>Todo Application</h1>
                <form onSubmit={handleSubmit(handleData)}>
                    <Grid
                        style={{ margin: "10px" }}
                        container
                        spacing={1}
                        direction="column"  >
                        <Grid item xs={6}>
                            <TextField
                                name="title"
                                label="Title"
                                variant="standard"
                                onChange={handelInputChange} />
                            <TextField
                                name="desc"
                                label="Description"
                                variant="standard"
                                onChange={handelInputChange} />
                            <TextField
                                name="priority"
                                type="number"
                                label="Priority"
                                variant="standard"
                                onChange={handelInputChange} />
                        </Grid>
                    </Grid>
                </form>    
                <button type="submit" variant="contained" color="primary">
                    Add
                </button>
            </Paper>
        </>
    );
}

Solution

  • You have quite a bit of things to do in order to get this form to console.log. First, as the other poster mentioned, the submit button needs to be within the form (and you probably want to uppercase that B in "<Button" so that you're using the MUI component.

              <form onSubmit={handleSubmit(handleData)}>
                <Grid
                  style={{ margin: "10px" }}
                  container
                  spacing={1}
                  direction="column"
                >
                  <Grid item xs={6}>
                    <TextField
                      name="title"
                      label="Title"
                      variant="standard"
                      onChange={handelInputChange}
                    />
                    ...
                  </Grid>
                </Grid>
                // Moved and renamed here
                <Button type="submit" variant="contained" color="primary">
                  Add
                </Button>
              </form>
    

    That solves your submit problem, but then you will notice that the console.log("data") will only ever contain an empty object {} -- this is because react-form-hooks needs to be given a FormProvider and made aware of the form elements in the form that it should control. To do this you need to register the component. I have added working code example on one way to complete this task.

    In this example, I created a generic FormFieldController wrapper that you can use to pass in whatever just about form fields you need. (I would not use this in production code, without cleanup, as it is only meant as an example):

    const FormFieldController = ({
      component: Component = TextField,
      name = "",
      defaultValue = "",
      label = "",
      validation = {},
      required = false,
      valueProp = "value",
      callbackProp = "onChange",
      onChange,
      ...rest
    }) => {
      const { control } = useFormContext();
    
      return (
        <Controller
          name={name}
          control={control}
          defaultValue={defaultValue}
          rules={validation}
          render={({
            field: { onChange: internalOnChange, value, ref },
            fieldState: { error }
          }) => {
            const pipes = {
              [valueProp]: value,
              [callbackProp]: function () {
                internalOnChange.apply(this, arguments);
    
                // Middleman callback to allow for onChange back to the caller, if needed
                if (onChange) {
                  onChange.apply(this, arguments);
                }
              }
            };
            return (
              <>
                <Component
                  id={name}
                  inputRef={ref}
                  caption={error ? error?.message : ""}
                  label={label}
                  {...pipes}
                  {...rest}
                />
              </>
            );
          }}
        />
      );
    };
    

    Working CodeSandbox Example