如何使用react-router在React.js中实现编辑表单回显与更新
解决React编辑表单初始化问题
要实现用路由传递的联系人数据初始化编辑表单,需对自定义useInput钩子和EditForm组件做以下修改:
1. 修改useInput钩子,支持初始值
当前钩子的enteredValue默认初始化为空字符串,我们需要让它接收外部传入的初始值,以此实现用路由数据初始化表单。
修改后的useInput代码:
import { useState } from "react"; const useInput = (validateValue, initialValue = '') => { const [enteredValue, setEnteredValue] = useState(initialValue) const [isTouched, setIsTouched] = useState(false) const valueIsValid = validateValue(enteredValue); const hasError = !valueIsValid && isTouched; const valueChangeHandler = (e) => { setEnteredValue(e.target.value) } const InputBlurHandler = (e) => { setIsTouched(true) } const reset = () => { setEnteredValue(''); setIsTouched(false) } return { value: enteredValue, isValid: valueIsValid, hasError, valueChangeHandler, InputBlurHandler, reset } }; export default useInput;
修改点:
- 给
useInput新增第二个参数initialValue,默认值为空字符串 - 初始化
enteredValue时使用initialValue代替硬编码的''
2. 在EditForm中用路由数据初始化表单字段
在EditForm组件中,从location.state拿到联系人数据后,将每个字段的值作为初始值传入对应的useInput调用,同时处理数据为空的边界情况(比如用户直接访问编辑页面)。
修改后的EditForm关键部分代码:
import React from 'react' import useInput from '../formHooks/hooks/use-input' import './EditForm.css' import LoadingSpinner from './LoadingSpinner' import {useLocation} from 'react-router-dom' const EditForm = (props) => { const location = useLocation(); const data = location.state || {}; // 处理数据为空的情况 // 用data中的对应字段作为初始值传入useInput const { value: enteredFirstName, isValid: enteredFirstNameIsValid, hasError: firstNameInputHasError, InputBlurHandler: firstNameBlurHandler, valueChangeHandler: firstNameChangedHandler, reset: resetFirstNameInput } = useInput(value => value.trim() !== "", data.firstName || '') const { value: enteredLastName, isValid: enteredLastNameIsValid, hasError: lastNameInputHasError, InputBlurHandler: lastNameBlurHandler, valueChangeHandler: lastNameChangedHandler, reset: resetLastNameInput } = useInput(value => value.trim() !== "", data.lastName || '') const { value: enteredEmail, isValid: enteredEmailIsValid, hasError: emailInputHasError, InputBlurHandler: emailBlurHandler, valueChangeHandler: emailChangedHandler, reset: resetEmailInput } = useInput(value => value.includes('@'), data.email || '') const { value: enteredPhoneNumber, isValid: enteredPhoneNumberIsValid, hasError: phoneNumberInputHasError, InputBlurHandler: phoneNumberBlurHandler, valueChangeHandler: phoneNumberChangedHandler, reset: resetPhoneNumberInput } = useInput(value => value.trim() !== "", data.phone || '') const { value: enteredAddress1, isValid: enteredAddress1IsValid, hasError: address1InputHasError, InputBlurHandler: address1BlurHandler, valueChangeHandler: address1ChangedHandler, reset: resetAddress1Input } = useInput(value => value.trim() !== "", data.address1 || '') const { value: enteredAddress2, valueChangeHandler: address2ChangedHandler, reset: resetAddress2Input } = useInput(value => value.trim() == "", data.address2 || '') const { value: enteredState, valueChangeHandler: stateChangedHandler, reset: resetStateInput } = useInput(value => value.trim() == "", data.state || '') const { value: enteredCountry, valueChangeHandler: countryChangedHandler, reset: resetCountryInput } = useInput(value => value.trim() == "", data.country || '') const { value: enteredAbout, isValid: enteredAboutIsValid, hasError: aboutInputHasError, InputBlurHandler: aboutBlurHandler, valueChangeHandler: aboutChangedHandler, reset: resetAboutInput } = useInput(value => value.trim() !== "", data.about || '') // 文件输入框(type="file")无法通过value属性初始化,若需展示已上传文件,可额外添加状态显示文件名或预览图 // 其余代码保持不变... } export default EditForm
修改点:
- 将
const data = location.state;改为const data = location.state || {};,避免数据为空时触发报错 - 每个
useInput调用都添加第二个参数,传入data中对应的字段值,用|| ''处理字段不存在的情况
3. 额外注意事项
- 确保路由配置正确,
/edit/:id路由对应的组件为EditForm - 提交表单时需传递联系人
id,方便后端定位要更新的数据,可在formSubmitHandler中修改:
props.onSaveContact({ id: data.id, // 添加id字段 firstName: enteredFirstName, lastName: enteredLastName, email: enteredEmail, phone: enteredPhoneNumber, address1: enteredAddress1, address2: enteredAddress2, state: enteredState, country: enteredCountry, file: enteredFile, about: enteredAbout })
内容的提问来源于stack exchange,提问作者Duke
相关产品推荐
相关产品推荐

