You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在ReactJS中使用useFormik时如何将UUID作为条目ID

在React Formik中提交表单时自动分配UUID

我在ReactJS中使用useFormik提交表单,已经定义了空值的initialValues,输入框通过value={formik.values.bookName}这类方式绑定值。现在希望提交时自动为ID分配UUID,同时让bookName、autherName等字段随用户输入值提交,但不清楚何时以及如何分配UUID。相关代码如下:

import React, { useState, useEffect } from 'react';
import { useFormik } from "formik";
import * as Yup from "yup";
import { Table, Button, Row, Col } from 'react-bootstrap';
import { v4 as uuid } from "uuid";


const getDataFromLs = () => {
    const data = localStorage.getItem('valueArray');
    if (data) {
        return JSON.parse(data)
    } else {
        return [];
    }
}

const formSchema = Yup.object({
    bookName:
        Yup.string()
            .required("لطفا نام کتاب را وارد نمایید")
            .min(3, "نام کتاب کمتر از 3 حرف نباشد"),

    autherName:
        Yup.string().required().min(4).max(10),

})

const FormikYupAddBook = () => {


    const [valueArray, setValueArray] = useState(getDataFromLs)
    const [id, setId] = useState('')

    useEffect(() => {
        localStorage.setItem('valueArray', JSON.stringify(valueArray))
        console.log('dddd', valueArray)
    }, [valueArray])

    const formik = useFormik({
        initialValues: {
            bookId: "",
            bookName: "",
            autherName: "",
        },
        validationSchema: formSchema,


        onSubmit(values) {
            
            localStorage.setItem('values', JSON.stringify(formik.values))

            setValueArray([...valueArray, values])
            console.log('vvvvv', valueArray);
        }


    })

    return (
        <div>
            <div style={{ width: "600px" }}>
                <form action="/action_page.php">
                    <div class="input-group">

                        <div class="input-group-btn">
                            <button style={{ height: "40px", width: "100px", backgroundColor: "blue" }} class="btn btn-default text-white" type="submit">submit<i class="glyphicon glyphicon-search"></i></button>
                        </div>
                        <input style={{ direction: "rtl" }} type="text" class="form-control" placeholder="Search" name="search" />
                    </div>
                </form>

            </div>
            <Row>
                <Col md={1} style={{ backgroundColor: 'pink' }}>
                    blue
                </Col>


                <Col md={6} style={{ backgroundColor: 'white' }}>
                    <input class="form-control form-control-lg" type="text" placeholder=".form-control-lg" />



                    <Table striped bordered hover>
                        <thead>
                            <tr>
                                <th>#</th>
                                <th>نام کتاب</th>
                                <th>نام نویسنده </th>

                            </tr>
                        </thead>
                        <tbody>
                            {

                                valueArray.map((book) =>


                                    <tr>
                                        <td>{book.bookId}</td>
                                        <td>{book.bookName}</td>
                                        <td>{book.autherName}</td>

                                    </tr>

                                )

                            }

                        </tbody>
                    </Table>

                </Col>



                <Col md={4} >
                    <div style={{
                        backgroundColor: "#E7E9EB !important",
                        color: "black !important", padding: "8px 16px !important",
                        border: "1px solid #ccc !important",
                        borderRadius: "5px"
                    }} class="container-fluid mt-3 w3-border w3-padding w3-round ws-grey" >
                        <form action="/action_page.php">
                            <div class="mb-3 mt-3">
                                <label for="email" class="form-label">Email:</label>
                                <input type="email" class="form-control" id="email" placeholder="Enter email" name="email" />
                            </div>
                            <div class="mb-3">
                                <label for="pwd" class="form-label">Password:</label>
                                <input type="password" class="form-control" id="pwd" placeholder="Enter password" name="pswd" />
                            </div>
                            <div class="form-check mb-3">
                                <label class="form-check-label">
                                    <input class="form-check-input" type="checkbox" name="remember" /> Remember me
                                </label>
                            </div>
                            <button type="submit" class="btn btn-primary">Submit</button>
                        </form>
                    </div>



                    <form onSubmit={formik.handleSubmit}>
                        <div>


                            <input

                                name="bookId"

                                value={formik.values.bookId}
                                onChange={() => {setId(uuid())}}

                            />
                            <input
                                style={{ fontSize: "10px", width: "300px", height: "40px", direction: "rtl" }}
                                className="form-control"
                                name="bookName"
                                placeholder="لطفا نام کتاب را وارد نمایید."
                                value={formik.values.bookName}
                                onChange={formik.handleChange}
                                onBlur={formik.bookName}
                            />
                            {formik.submitCount > 0 && formik.errors.bookName && (
                                <p>{formik.errors.bookName}</p>
                            )}
                        </div>
                        <div>
                            <input
                                style={{ fontSize: "10px", width: "300px", height: "40px", direction: "rtl" }}
                                name="autherName"
                                placeholder="لطفا نام نویسنده را وارد نمایید."
                                value={formik.values.autherName}
                                onChange={formik.handleChange}
                                onBlur={formik.handleBlur}
                            />
                            {formik.submitCount > 0 && formik.errors.autherName && (
                                <p>{formik.errors.autherName}</p>
                            )}
                        </div>

                        <button >Submit</button>
                    </form>


                </Col>

                <Col md={1} style={{
                    backgroundColor: 'purple',
                }}>


                </Col>
            </Row>

        </div >
    )
}

export default FormikYupAddBook

解决方案

不需要单独维护id状态,也不需要给bookId做输入框绑定,直接在表单提交的onSubmit函数里生成UUID,然后合并到提交的values中即可,具体步骤如下:

1. 移除不必要的代码

  • 删除单独的id状态:const [id, setId] = useState('')
  • 删除页面中bookId的输入框组件,因为这个ID是自动生成的,不需要用户输入

2. 修改Formik的onSubmit逻辑

在onSubmit函数里,先生成UUID,然后把它添加到提交的values对象中,再存入localStorage和状态数组:

onSubmit(values) {
  // 生成UUID并合并到表单值中
  const bookWithId = {
    ...values,
    bookId: uuid()
  };
  
  localStorage.setItem('values', JSON.stringify(bookWithId));
  // 使用函数式更新确保拿到最新状态
  setValueArray(prevArray => [...prevArray, bookWithId]);
  // 提交后重置表单
  formik.resetForm();
}

3. 修正表单绑定细节

  • 把bookName输入框的onBlur={formik.bookName}改为onBlur={formik.handleBlur},否则表单校验会失效
  • 给提交按钮添加type="submit"属性,避免默认表单跳转行为

完整修改后的代码

import React, { useState, useEffect } from 'react';
import { useFormik } from "formik";
import * as Yup from "yup";
import { Table, Button, Row, Col } from 'react-bootstrap';
import { v4 as uuid } from "uuid";


const getDataFromLs = () => {
    const data = localStorage.getItem('valueArray');
    if (data) {
        return JSON.parse(data)
    } else {
        return [];
    }
}

const formSchema = Yup.object({
    bookName:
        Yup.string()
            .required("لطفا نام کتاب را وارد نمایید")
            .min(3, "نام کتاب کمتر از 3 حرف نباشد"),

    autherName:
        Yup.string().required().min(4).max(10),

})

const FormikYupAddBook = () => {
    const [valueArray, setValueArray] = useState(getDataFromLs)

    useEffect(() => {
        localStorage.setItem('valueArray', JSON.stringify(valueArray))
    }, [valueArray])

    const formik = useFormik({
        initialValues: {
            bookName: "",
            autherName: "",
        },
        validationSchema: formSchema,
        onSubmit(values) {
            // 生成UUID并合并到表单数据
            const bookWithId = {
                ...values,
                bookId: uuid()
            };
            
            localStorage.setItem('values', JSON.stringify(bookWithId));
            // 函数式更新确保状态正确
            setValueArray(prev => [...prev, bookWithId]);
            // 重置表单
            formik.resetForm();
        }
    })

    return (
        <div>
            <div style={{ width: "600px" }}>
                <form action="/action_page.php">
                    <div className="input-group">
                        <div className="input-group-btn">
                            <button style={{ height: "40px", width: "100px", backgroundColor: "blue" }} className="btn btn-default text-white" type="submit">submit<i className="glyphicon glyphicon-search"></i></button>
                        </div>
                        <input style={{ direction: "rtl" }} type="text" className="form-control" placeholder="Search" name="search" />
                    </div>
                </form>
            </div>
            <Row>
                <Col md={1} style={{ backgroundColor: 'pink' }}>
                    blue
                </Col>
                <Col md={6} style={{ backgroundColor: 'white' }}>
                    <input className="form-control form-control-lg" type="text" placeholder=".form-control-lg" />
                    <Table striped bordered hover>
                        <thead>
                            <tr>
                                <th>#</th>
                                <th>نام کتاب</th>
                                <th>نام نویسنده </th>
                            </tr>
                        </thead>
                        <tbody>
                            {valueArray.map((book) => (
                                <tr key={book.bookId}>
                                    <td>{book.bookId}</td>
                                    <td>{book.bookName}</td>
                                    <td>{book.autherName}</td>
                                </tr>
                            ))}
                        </tbody>
                    </Table>
                </Col>
                <Col md={4} >
                    <div style={{
                        backgroundColor: "#E7E9EB",
                        color: "black", padding: "8px 16px",
                        border: "1px solid #ccc",
                        borderRadius: "5px"
                    }} className="container-fluid mt-3 w3-border w3-padding w3-round ws-grey" >
                        <form action="/action_page.php">
                            <div className="mb-3 mt-3">
                                <label htmlFor="email" className="form-label">Email:</label>
                                <input type="email" className="form-control" id="email" placeholder="Enter email" name="email" />
                            </div>
                            <div className="mb-3">
                                <label htmlFor="pwd" className="form-label">Password:</label>
                                <input type="password" className="form-control" id="pwd" placeholder="Enter password" name="pswd" />
                            </div>
                            <div className="form-check mb-3">
                                <label className="form-check-label">
                                    <input className="form-check-input" type="checkbox" name="remember" /> Remember me
                                </label>
                            </div>
                            <button type="submit" className="btn btn-primary">Submit</button>
                        </form>
                    </div>
                    <form onSubmit={formik.handleSubmit}>
                        <div>
                            <input
                                style={{ fontSize: "10px", width: "300px", height: "40px", direction: "rtl" }}
                                className="form-control"
                                name="bookName"
                                placeholder="لطفا نام کتاب را وارد نمایید."
                                value={formik.values.bookName}
                                onChange={formik.handleChange}
                                onBlur={formik.handleBlur}
                            />
                            {formik.submitCount > 0 && formik.errors.bookName && (
                                <p>{formik.errors.bookName}</p>
                            )}
                        </div>
                        <div>
                            <input
                                style={{ fontSize: "10px", width: "300px", height: "40px", direction: "rtl" }}
                                name="autherName"
                                placeholder="لطفا نام نویسنده را وارد نمایید."
                                value={formik.values.autherName}
                                onChange={formik.handleChange}
                                onBlur={formik.handleBlur}
                            />
                            {formik.submitCount > 0 && formik.errors.autherName && (
                                <p>{formik.errors.autherName}</p>
                            )}
                        </div>
                        <button type="submit">Submit</button>
                    </form>
                </Col>
                <Col md={1} style={{ backgroundColor: 'purple' }}></Col>
            </Row>
        </div >
    )
}

export default FormikYupAddBook

关键说明

  • UUID生成时机:在onSubmit里生成,确保每次提交都能得到唯一ID,不需要提前存储
  • 状态更新:使用setValueArray(prev => [...prev, bookWithId])的函数式更新,避免闭包导致的旧状态问题
  • 表单重置:提交后调用formik.resetForm()清空表单,提升用户体验
  • 代码简化:移除了无用的bookId输入框和单独的id状态,逻辑更清晰

内容的提问来源于stack exchange,提问作者hhamidy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 22:14:54