React+Node用户添加优化:解决唯一ID与key prop警告问题
问题:用户唯一ID生成与React列表key警告解决
我在基于React和Node.js的用户管理系统中,尝试通过前端维护userId为新增用户分配唯一ID,但控制台出现警告:Warning: Each child in a list should have a unique 'key' prop.。需要实现可靠的用户唯一ID生成方案,并消除该警告。以下是我的相关代码:
一、前端组件代码
AddUserData组件
import axios from "axios"; import { useState } from "react"; const AddUserData: React.FC<{ getUserAxios: () => void }> = ({ getUserAxios, }) => { const [Name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassWord] = useState(""); const [userId, setUserId] = useState(1); const getUserData = () => { const newUserData = { id:userId, Name, email, password, }; axios({ method: "post", url: "http://localhost:3001/addNewUser", data: newUserData, }) .then(function (response) { console.log(response); setTimeout(() => { getUserAxios(); }, 1000); }) .catch(function (error) { console.log(error); }); setName(""); setEmail(""); setPassWord(""); setUserId((prevUserId) => prevUserId + 1); }; return ( <> <form> <div className="input-group mb-3"> <span className="input-group-text" id="basic-addon1"> 🙂 </span> <input type="text" className="form-control" placeholder="User Firstname" aria-label="User Firstname" aria-describedby="basic-addon1" value={Name} onChange={(e) => setName(e.target.value)} /> </div> <div className="input-group mb-3"> <span className="input-group-text" id="basic-addon1"> 🔑 </span> <input type="text" className="form-control" placeholder="User Lastname" aria-label="User Lastname" aria-describedby="basic-addon1" value={password} onChange={(e) => setPassWord(e.target.value)} /> </div> <div className="input-group mb-3"> <span className="input-group-text" id="basic-addon2"> 💌 </span> <input type="text" className="form-control" placeholder="Users Email" aria-label="Users Email" aria-describedby="basic-addon2" value={email} onChange={(e) => setEmail(e.target.value)} /> </div> <button type="button" className="btn btn-primary mx-2" onClick={getUserData} > Add </button> <button type="button" className="btn btn-secondary"> Cancel </button> </form> </> ); }; export default AddUserData;
UserDataTable组件
import axios from "axios"; import { useEffect, useState } from "react"; import AddUserData from "../AddUserData/AddUserData"; import { UserType } from "../store/stype-store"; const UserDataTable = () => { const [users, setUsers] = useState <UserType[]>([]); const getUserAxios = () => { axios .get("http://localhost:3001/usersData") .then((res) => { console.log("Response from axios", res.data); const { allUsers } = res.data; console.log("allUsers from axios", allUsers); setUsers(allUsers); }) .catch((err) => { console.log("err from axios", err.message); }); }; useEffect(() => { getUserAxios(); }, []); const userMap = users.map((user: UserType, index) => { return ( <tr key={user.id}> <th scope="row">{index}</th> <td>{user.Name}</td> <td>{user.password}</td> <td>{user.email}</td> </tr> ); }); return ( <> <div className="col-lg-7 p-3 p-lg-5 pt-lg-3 "> <table className="table table-striped"> <thead> <tr> <th scope="col">ID</th> <th scope="col">Name</th> <th scope="col">Password</th> <th scope="col">E-Mail</th> </tr> </thead> <tbody>{userMap}</tbody> </table> </div> <div className="col-lg-4 p-3 p-lg-5 pt-lg-3"> <AddUserData getUserAxios={getUserAxios} /> </div> </> ); }; export default UserDataTable;
二、Node后端代码
const express = require("express"); const cors = require("cors"); const app = express(); const port = 3001; app.use(express.json()); app.use( cors({ origin: "*", }) ); let previousUserData = [ { id: 1, Name: "RAHUL", password: "1w2e2w", email: "affj@gmail.com", }, { id:2, Name: "CHAHUL", password: "1w2e2w", email: "affj@gmail.com", }, ]; app.get("/usersData", (req, res) => { res.send({ status: 200, allUsers: previousUserData }); }); app.post("/addNewUser", (req, res) => { const { id, Name, password, email } = req.body; if (Name && password && email) { previousUserData = [...previousUserData, { id, Name, password, email }]; res.send({ status: 200, msg: "user added", allUsers: previousUserData }); } else { res.send({ status: 500, msg: "something went wrong" }); } }); app.listen(port, () => { console.log("Server started on port " + port); });
解决方案
一、实现可靠的用户唯一ID生成
前端维护ID存在致命问题:页面刷新后userId会重置为1,多标签页操作也会导致ID重复。唯一可靠的方案是由后端负责生成唯一ID,提供两种实现方式:
方案1:基于现有用户最大ID自增
修改Node后端的/addNewUser接口,自动计算新用户ID:
app.post("/addNewUser", (req, res) => { const { Name, password, email } = req.body; if (Name && password && email) { // 生成唯一ID:取现有用户最大ID+1,列表为空时初始为1 const newId = previousUserData.length > 0 ? Math.max(...previousUserData.map(user => user.id)) + 1 : 1; const newUser = { id: newId, Name, password, email }; previousUserData = [...previousUserData, newUser]; res.send({ status: 200, msg: "user added", allUsers: previousUserData }); } else { res.send({ status: 500, msg: "something went wrong" }); } });
同时修改前端AddUserData组件,删除userId相关状态:
import axios from "axios"; import { useState } from "react"; const AddUserData: React.FC<{ getUserAxios: () => void }> = ({ getUserAxios, }) => { const [Name, setName] = useState(""); const [email, setEmail] = useState(""); const [password, setPassWord] = useState(""); const getUserData = () => { // 不再传递id字段,由后端生成 const newUserData = { Name, email, password, }; axios({ method: "post", url: "http://localhost:3001/addNewUser", data: newUserData, }) .then(function (response) { console.log(response); setTimeout(() => { getUserAxios(); }, 1000); }) .catch(function (error) { console.log(error); }); setName(""); setEmail(""); setPassWord(""); }; // return部分保持不变 }; export default AddUserData;
方案2:使用UUID生成全局唯一ID(适合分布式场景)
先安装uuid依赖:npm install uuid
后端修改代码:
const { v4: uuidv4 } = require('uuid'); // ... app.post("/addNewUser", (req, res) => { const { Name, password, email } = req.body; if (Name && password && email) { // 用UUID生成唯一ID const newUser = { id: uuidv4(), Name, password, email }; previousUserData = [...previousUserData, newUser]; res.send({ status: 200, msg: "user added", allUsers: previousUserData }); } else { res.send({ status: 500, msg: "something went wrong" }); } });
前端同样删除userId相关状态,无需传递id字段。
二、消除React列表key警告
你当前的UserDataTable组件中,已经给<tr>设置了key={user.id},这是正确的写法。之前出现警告的根源是前端生成的ID重复,导致key冲突。解决完ID唯一性问题后,该警告会自动消失。
额外注意:不要使用index作为列表key(你当前仅在<th>中展示index,key仍使用user.id,这个做法是正确的)。
内容的提问来源于stack exchange,提问作者user20404911
相关产品推荐
相关产品推荐

