【问题标题】:Submitting a form from within another form in React在 React 中从另一个表单中提交表单
【发布时间】:2021-03-23 22:32:20
【问题描述】:

我有一个带有表单的组件,AddExpense.tsx。表单应该有添加另一个类别的选项。这是一个单独的、解耦的表单,存储在 AddCategory.tsx 组件中。 我需要这个组件以可视方式出现在 AddExpense 表单中,但不幸的是,这似乎破坏了 AddCategory 事件处理程序。如何嵌套这些表单并让它们与单独的 submitHandlers 一起使用?

AddExpense.tsx:

export const AddExpense = (props: AddExpenseProps) => {
  const { user } = useAuth()
  const [addCategoryIsHidden, setAddCategoryIsHidden] = useState(true)
  const [state, setState] = useState({
    category: '',
    amount: 0, 
    notes: '', 
    date: '',
    user_id: user.info.user_id
  })
  const [validated, setValidated] = useState(false)

  const { categories } = props
  

  const handleSubmit = async(e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault()
    console.log('yo')
    const form = e.currentTarget;
    if (form.checkValidity() === true) {
      
      await fetch('/api/addExpense', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(state)
      }).then(result => {
        console.log(result)
        if (result.status === 200) {
          console.log('success!')
        } else {
          console.log('error!')
        }
      })

    } else {
      e.preventDefault();
      e.stopPropagation();
    } 
    setValidated(true);
  }

  return (
    <div className='form-wrapper'>
      <Form noValidate validated={validated} onSubmit={handleSubmit}>
        <Form.Group controlId='expenseCategory'>
          <Form.Label>Category</Form.Label>
          <Form.Control 
            required as='select'
            onChange={(e) => setState({...state, category: e.target.value })}
          >
            {categories.map((category, index) => (
              <option key={index} value={category.category_name}>{category.category_name}</option>
            ))}
          </Form.Control>
        </Form.Group>
        <a
        onClick={(e) => setAddCategoryIsHidden(false)}
        style={{cursor: 'pointer', color: 'blue', textDecoration: 'underline', textDecorationColor: 'blue'}}>
          Add a new category
        </a>
        <AddCategory hidden={addCategoryIsHidden} type='expenses'/>
        <Form.Group controlId='expenseAmount'>
          <Form.Label>Amount</Form.Label>
          <Form.Control 
            required 
            type="number"
            step=".01"
            onChange={(e) => setState({...state, amount: parseFloat(e.target.value) })}/>
          <Form.Control.Feedback type="invalid">
            Please provide a valid amount.
          </Form.Control.Feedback>
        </Form.Group> 
        <Form.Group controlId="expenseNotes">
          <Form.Label>Notes</Form.Label>
          <Form.Control 
            as="textarea" 
            rows={3} 
            placeholder="(optional)"
            onChange={(e) => setState({...state, notes: e.target.value})}/>
        </Form.Group>
        <Form.Group controlId="expenseDate">
          <Form.Label>Date</Form.Label>
          <Form.Control 
            required 
            type="date" 
            name='date_of_expense'
            onChange={(e) => setState({...state, date: e.target.value})}/>
          <Form.Control.Feedback type="invalid">
            Please select a date.
          </Form.Control.Feedback>
        </Form.Group>
        <Button variant="primary" type="submit">
          Submit
        </Button>
      </Form>
    </div>
  )
}

AddCategory.tsx:

export const AddCategory = ({ type, hidden }: AddCategoryProps) => {
  const [newCategory, setNewCategory] = useState<string>()
  const { user } = useAuth()

  const handleSubmit = async(e: React.FormEvent<HTMLFormElement>) => {
    await fetch(`/api/addCategory`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        category_name: newCategory,
        user_id: user.info.user_id,
        type: type})
    })
  }

  return (
    hidden ? null : 
    <Form onSubmit={handleSubmit}>
      <Form.Group controlId='addCategory'>
        <Form.Control
          required
          type="text"
          placeholder="new category name"
          onChange={(e) => setNewCategory(e.target.value)}>
        </Form.Control>
      </Form.Group>
      <Button variant="primary" type="submit">
        Submit
      </Button>
    </Form>
  )
}

【问题讨论】:

    标签: reactjs typescript forms


    【解决方案1】:

    HTML5 规范不允许嵌套&lt;form&gt; 元素(请参阅discussion)。我不确定您使用的是什么表单库,但它可能会遵守该约定,并且当您将一个 &lt;Form&gt; 嵌套在另一个表单库中时会出现错误。

    你需要

    • 通过将&lt;AddCategory&gt; 移动到&lt;AddExpense&gt; 的底部和父&lt;Form&gt; 组件之外,或其他类似模态的位置来重组您的组件,或者

    • 不要在AddCategory 中使用&lt;Form&gt;;它看起来相当简单,因此您可以将输入连接到useState 并使用按钮的onClick 处理表单“提交”,或者

    • AddCategory 中删除包装&lt;Form&gt; 并使用父组件的onSubmit 处理类别创建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-07
      • 2016-03-21
      • 1970-01-01
      • 2013-08-18
      相关资源
      最近更新 更多