3

I am using MUI for components. After days of painful debugging, I found out that my form isn't calling the onSubmit method while the Box component is used to wrap the form. Please find below minimal ex. Why this is happening? onClick works fine though. Isn't Box component a valid use case here. Should I be using API differently.

import { Box, Button, TextField } from '@mui/material';

export function MainForm() {

  const submitHandler = (e) => {
    console.log('submit called');
    e.preventDefault();
  }

  return (
    <div>
      <Box
        component="form"
      >
        <form onSubmit={submitHandler}>
          <TextField />
          <Button type="submit">Submit</Button>
        </form>
      </Box>
    </div >
  )
}
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230
garg10may
  • 5,794
  • 11
  • 50
  • 91
  • 3
    I think that output of this is two wrapped `
    ` inside each other, and button triggering the upper one. Why are you exactly using `component='form'` there?
    – Wraithy Oct 29 '21 at 09:21
  • I just realized it works perfectly fine without `component=form`. I thought seeing the API I need to tell it what component I want to wrap, I felt a bit sceptical but thought maybe it's `mui` way. – garg10may Oct 29 '21 at 09:26
  • Ok, here it is https://mui.com/components/box/ - `For non-MUI components, use the component prop.` – garg10may Oct 29 '21 at 09:28

2 Answers2

7

Since you defined your Box component as a form, you have to place your onSubmit inside it.

<Box component="form" onSubmit={submitHandler}>
    <TextField />
    <Button type="submit">Submit</Button>
</Box>

You are overriding your MUI component, so the Box is already assuming itself as a form component.

Consider reading the Overriding MUI components from the MUI documentation.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Rui Castro
  • 108
  • 7
5

Since the accepted answer doesn't really explain the reason why your code didn't work, here are some notes:

Box component='form' means that the Box is actually a form component with extra junk, your code would look like this as a result:

<form {...extraPropsFromBox}>
  <form onSubmit={submitHandler}>
    <TextField />
    <Button type="submit">Submit</Button>
  </form>
</form>

Nested form is not supported in HTML 5 and using it is asking for trouble, in this case it probably ignores the submit handler in the nested form, the fix is remove the outer one. If you don't have a need to style the form container, just use a normal form tag. Use Box + form if you want to apply some styles quickly:

<Box component="form" onSubmit={submitHandler} sx={{ maxWidth: 300, bgcolor: 'gray' }}>
    <TextField />
    <Button type="submit">Submit</Button>
</Box>

I thought seeing the API I need to tell it what component I want to wrap

All MUI components have a component prop that allows you to override the root component. Below is what the Box looks like under-the-hook. You do not have to specify the component because they all have a default value:

function Box({ component = 'div', ...boxProps }) {
  return <component {...boxProps} />
}
NearHuscarl
  • 66,950
  • 18
  • 261
  • 230