React组件需点击两次按钮才渲染的问题求解
解决方案:修复「Next Step」首次点击无响应问题
问题根源
首次点击无响应是因为useState的异步更新特性:点击按钮触发handleSubmit后,submitting状态不会立刻更新,导致Button组件的handleNextButton第一次执行时,submitting仍为初始值false,不满足跳转条件;第二次点击时状态已更新,才会触发跳转。
同时代码中存在useState声明错误,会导致套餐周期切换逻辑异常,需要先修复。
步骤1:修复套餐周期的useState声明错误
在app.js中,isMonthly的状态声明错误,第二个参数应为状态更新函数,而非状态值:
// 错误代码 const [isMonthly, isYearly] = useState('Monthly'); // 改为 const [isMonthly, setIsMonthly] = useState('Monthly');
同步修改handleSwitch函数,正确切换周期:
// 错误代码 const handleSwitch = () => { isYearly(!isMonthly) }; // 改为 const handleSwitch = () => { setIsMonthly(current => current === 'Monthly' ? 'Yearly' : 'Monthly'); };
步骤2:移除冗余的submitting状态,直接在验证通过后跳转
submitting状态是多余的,可在表单验证通过后直接执行导航,避免依赖异步更新的状态。
修改App.js
- 删除
submitting相关的状态声明:
// 删除这一行 const [submitting, setSubmitting] = useState(false);
- 修改
handleSubmit函数,仅负责更新错误状态:
// 保留原验证逻辑 const validateValues = (inputValues) => { let errors = {}; if (inputValues.name.length < 1) { errors.name = "This field is required"; } if (inputValues.email.length < 1) { errors.email = "This field is required"; } if (inputValues.phone.length < 1) { errors.phone = "This field is required"; } return errors; }; // 修改handleSubmit,接收验证结果并更新错误状态 const handleSubmit = (event, validationErrors) => { event.preventDefault(); setErrors(validationErrors); };
- 更新
Info路由的props,传递validateValues函数:
<Route path="/" element={<Info inputFields={inputFields} errors={errors} handleChange={handleChange} handleSubmit={handleSubmit} validateValues={validateValues} />} />
修改Info组件
在Info组件中使用useNavigate处理验证和跳转:
import React from "react"; import { useNavigate } from 'react-router-dom'; import Button from '../Button/Button'; export default function Info({ inputFields, errors, handleChange, handleSubmit, validateValues }) { const navigate = useNavigate(); const handleFormSubmit = (e) => { const validationErrors = validateValues(inputFields); handleSubmit(e, validationErrors); // 验证通过直接跳转 if (Object.keys(validationErrors).length === 0) { navigate('/Plan'); } }; return ( <form onSubmit={handleFormSubmit}> {/* 姓名输入框示例 */} <div className="form-group"> <label>Name</label> <input type="text" name="name" value={inputFields.name} onChange={handleChange} className={errors.name ? "input-error" : ""} /> {errors.name && <span className="error-message">{errors.name}</span>} </div> {/* 邮箱、电话输入框逻辑类似,省略 */} <Button errors={errors} /> </form> ); }
修改Button.js
移除依赖submitting的跳转逻辑,首页按钮仅作为表单提交按钮,跳转逻辑已在Info组件中处理:
const handleNextButton = (e) => { if (location.pathname === "/Plan") { navigate('/AddOn') } if (location.pathname === "/AddOn") { navigate('/Summary') } if (location.pathname === "/Summary") { navigate('/Confirm') } }
替代方案:保留submitting状态,用useEffect监听跳转
如果一定要保留submitting状态,可通过useEffect监听状态变化触发跳转:
修改App.js
- 添加重置
submitting的函数:
const resetSubmitting = () => setSubmitting(false);
- 将
resetSubmitting传递给Info组件:
<Route path="/" element={<Info inputFields={inputFields} errors={errors} submitting={submitting} handleChange={handleChange} handleSubmit={handleSubmit} resetSubmitting={resetSubmitting} />} />
修改Info组件
添加useEffect监听状态变化:
import React, { useEffect } from "react"; import { useNavigate } from 'react-router-dom'; export default function Info({ inputFields, errors, submitting, handleChange, handleSubmit, resetSubmitting }) { const navigate = useNavigate(); useEffect(() => { // 验证通过且处于提交状态时跳转 if (submitting && Object.keys(errors).length === 0) { navigate('/Plan'); resetSubmitting(); // 重置状态避免重复跳转 } }, [submitting, errors, navigate, resetSubmitting]); return ( <form onSubmit={handleSubmit}> {/* 表单内容 */} <Button errors={errors} submitting={submitting} /> </form> ); }
内容的提问来源于stack exchange,提问作者MCDoodle
相关产品推荐
相关产品推荐

