React表单无法提交:代码报错排查及修改方案咨询
React表单提交MongoDB的代码错误修复方案
问题背景
在React中实现了一个任务创建表单,意图将表单值保存到MongoDB的tasks集合,但运行代码时出现了Hook调用错误、变量未定义等一系列问题。
原代码
import React, { useState, useEffect } from 'react'; import 'bootstrap/dist/css/bootstrap.css'; import axios from 'axios'; export default function Task({}) { const loggedInUser = localStorage.getItem('loggedInUser') const [taskValues, setTaskValues] = useState({ task: '', userStory: ' ', // Default value createdBy: loggedInUser, // Default value status: ' ', // Default value }); const [allTask, setAllTask] = useState([{}]); const [assigned, setAllAssign] = useState([]); const[allStories, setAllStories] = useState([{}]); const assignedUserStories = allStories.filter((story) => { return assigned.some(({ user_story_id }) => user_story_id === story._id) }); const handleInputChange = (event) => { const { name, value } = event.target; setTaskValues({ ...taskValues, [name]: value }); }; // Post taskValues data to your server endpoint axios.post('http://localhost:9000/createTask', taskValues) .then((res) => { if (res.data) { alert('Task creation Successful'); } }) .catch((err) => { alert('Error in creating the task'); }); }; useEffect(() => { axios.get('http://localhost:9000/getTaskList').then(function (response) { const Taskdata = response.data; setAllTask(Taskdata); }); axios.get('http://localhost:9000/getUserstory').then(function (response) { const Allstories = response.data; setAllStories(Allstories); }); axios.get('http://localhost:9000/getAssignedstories').then(function (response) { const Allassignedstories = response.data; setAllAssign(Allassignedstories); }); }, []); const handleSubmit = (event) => { event.preventDefault(); return ( <div className="container mt-5"> <div className="row justify-content-center"> <div className="col-md-6 col-lg-4"> <div className="card"> <div className="card-body"> <h2 className="card-title">Create a New Task</h2> <form onSubmit={handleSubmit}> <div className="form-group"> <label>Task:</label> <textarea className="form-control" name="task" value={taskValues.task} onChange={handleInputChange} /> </div> <div className="form-group"> <label>User Story:</label> <select className="form-control" name="userStory" value={taskValues.userStory} onChange={handleInputChange} > {assignedUserStories.map((stories) => <option key={stories._id} value={stories._id}>{stories.user_story}</option> )} </select> </div> <div className="form-group"> <label>Created by:</label> <select className="form-control" name="createdBy" value={taskValues.createdBy} onChange={handleInputChange} > <option value="user1">User 1</option> <option value="user2">User 2</option> <option value="user3">User 3</option> </select> </div> <div className="form-group"> <label>Status:</label> <select className="form-control" name="status" value={taskValues.status} onChange={handleInputChange} > <option value="New">New</option> <option value="In Progress">In Progress</option> <option value="Awaiting Confirmation">Awaiting Confirmation</option> <option value="Completed">Completed</option> </select> </div> <button type="submit" className="btn btn-primary btn-block"> Create Task </button> </form> </div> </div> </div> </div> </div> ); }
报错信息
src\components\Task.js Line 48:5: React Hook "useEffect" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks Line 51:7: 'setAllTask' is not defined no-undef Line 56:7: 'setAllStories' is not defined no-undef Line 61:7: 'setAllAssign' is not defined no-undef Line 86:28: 'taskValues' is not defined no-undef Line 87:31: 'handleInputChange' is not defined no-undef Line 96:28: 'taskValues' is not defined no-undef Line 97:31: 'handleInputChange' is not defined no-undef Line 99:22: 'assignedUserStories' is not defined no-undef Line 112:28: 'taskValues' is not defined
具体修改步骤
1. 修复代码结构错误
原代码中handleInputChange函数结束后,错误地添加了一个额外的};,导致后续的useEffect、handleSubmit和组件返回部分都被抛出了组件函数的作用域,这是所有"未定义"错误的核心原因。需要删除这个多余的};,并将原本放在外层的axios.post请求逻辑移到handleSubmit函数内部。
2. 完善handleSubmit函数
原handleSubmit函数只有阻止默认行为的逻辑,没有实际的提交操作。需要把发送POST请求的代码移到这里,确保只有点击提交按钮时才触发数据提交,还可以在提交成功后重置表单:
const handleSubmit = (event) => { event.preventDefault(); // Post taskValues data to your server endpoint axios.post('http://localhost:9000/createTask', taskValues) .then((res) => { if (res.data) { alert('Task creation Successful'); // 提交成功后重置表单 setTaskValues({ task: '', userStory: '', createdBy: loggedInUser || 'user1', status: 'New', }); } }) .catch((err) => { alert('Error in creating the task'); }); };
3. 修正状态默认值
原userStory和status的默认值是空格' ',但下拉选项的value中没有空格,会导致初始状态下拉框没有选中项。建议改为空字符串或者匹配选项的默认值(比如status设为'New'),同时给createdBy增加兜底默认值,避免localStorage无值时出错:
const [taskValues, setTaskValues] = useState({ task: '', userStory: '', createdBy: loggedInUser || 'user1', status: 'New', });
4. 确保Hooks在组件内部调用
修正结构后,useEffect会回到组件函数内部,符合React Hooks的调用规则,解决"React Hook cannot be called at the top level"的错误。
修正后的完整代码
import React, { useState, useEffect } from 'react'; import 'bootstrap/dist/css/bootstrap.css'; import axios from 'axios'; export default function Task({}) { const loggedInUser = localStorage.getItem('loggedInUser'); const [taskValues, setTaskValues] = useState({ task: '', userStory: '', createdBy: loggedInUser || 'user1', status: 'New', }); const [allTask, setAllTask] = useState([{}]); const [assigned, setAllAssign] = useState([]); const [allStories, setAllStories] = useState([{}]); const assignedUserStories = allStories.filter((story) => { return assigned.some(({ user_story_id }) => user_story_id === story._id); }); const handleInputChange = (event) => { const { name, value } = event.target; setTaskValues({ ...taskValues, [name]: value }); }; useEffect(() => { axios.get('http://localhost:9000/getTaskList').then(function (response) { const Taskdata = response.data; setAllTask(Taskdata); }); axios.get('http://localhost:9000/getUserstory').then(function (response) { const Allstories = response.data; setAllStories(Allstories); }); axios.get('http://localhost:9000/getAssignedstories').then(function (response) { const Allassignedstories = response.data; setAllAssign(Allassignedstories); }); }, []); const handleSubmit = (event) => { event.preventDefault(); axios.post('http://localhost:9000/createTask', taskValues) .then((res) => { if (res.data) { alert('Task creation Successful'); setTaskValues({ task: '', userStory: '', createdBy: loggedInUser || 'user1', status: 'New', }); } }) .catch((err) => { alert('Error in creating the task'); }); }; return ( <div className="container mt-5"> <div className="row justify-content-center"> <div className="col-md-6 col-lg-4"> <div className="card"> <div className="card-body"> <h2 className="card-title">Create a New Task</h2> <form onSubmit={handleSubmit}> <div className="form-group"> <label>Task:</label> <textarea className="form-control" name="task" value={taskValues.task} onChange={handleInputChange} required /> </div> <div className="form-group"> <label>User Story:</label> <select className="form-control" name="userStory" value={taskValues.userStory} onChange={handleInputChange} required > <option value="">Select a User Story</option> {assignedUserStories.map((story) => ( <option key={story._id} value={story._id}> {story.user_story} </option> ))} </select> </div> <div className="form-group"> <label>Created by:</label> <select className="form-control" name="createdBy" value={taskValues.createdBy} onChange={handleInputChange} > <option value="user1">User 1</option> <option value="user2">User 2</option> <option value="user3">User 3</option> </select> </div> <div className="form-group"> <label>Status:</label> <select className="form-control" name="status" value={taskValues.status} onChange={handleInputChange} > <option value="New">New</option> <option value="In Progress">In Progress</option> <option value="Awaiting Confirmation">Awaiting Confirmation</option> <option value="Completed">Completed</option> </select> </div> <button type="submit" className="btn btn-primary btn-block"> Create Task </button> </form> </div> </div> </div> </div> </div> ); }
内容的提问来源于stack exchange,提问作者Encipher
相关产品推荐
相关产品推荐

