TypeScript+React ContextAPI中setUser意外令牌错误修复及数据添加问题
问题描述
作为TypeScript新手,我正在使用React Context API维护用户对象数组,尝试将uploadState的信息合并到setUser时触发了Unexpected Token错误,无法将uploadState添加到用户数组中。相关代码如下:
ContextAPI代码
import { createContext, useState } from "react"; import { UserType } from "../Reducers/Upload"; type UserContextProviderType = { children: React.ReactNode; }; const intionalState: UserType[] = [ { name: "", phoneNumber: "", partyName: "", userImage: "" } as UserType, ]; type UserContextType = { user: UserType[]; setUser: React.Dispatch<React.SetStateAction<UserType[]>>; }; export const UserContext = createContext<UserContextType | null>(null); export const UserState = ({ children }: UserContextProviderType) => { const [user, setUser] = useState<UserType[]>(intionalState); return ( <UserContext.Provider value={{ user, setUser }}> {children} </UserContext.Provider> ); };
UserType定义
export type UserType = { name: string; phoneNumber: string; partyName: string; userImage: string; };
UploadDetails组件代码(错误位置)
import { useContext, useReducer, useRef, useState } from "react"; import InputField from "../components/InputField"; import Button from "../components/Button"; import Image from "../components/Image"; import CommonStyle from "../Style/CommonStyle.module.css"; import UploadStyle from "../Style/UploadDetails.module.css"; import { intionalUploadState, uploadReducer } from "../Reducers/UploadReducer"; import defaultPic from "../assets/defaultPic.png"; import { UserContext } from "../context/UserContext"; export default function UploadDetails() { const inputRef = useRef<HTMLInputElement>(null); const [image, setImage] = useState<string>(defaultPic); const [uploadState, dispatch] = useReducer( uploadReducer, intionalUploadState ); const context = useContext(UserContext) const handleClick = (event: React.MouseEvent) => { event.preventDefault(); context?.setUser(prev => {return [...prev, {...context.user? ,context.user?.concate[uploadState]}]}) }; const imageUpload = () => { inputRef.current?.click(); }; const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => { switch (event.target.name) { case "name": dispatch({ type: event.target.name, payload: event.target.value }); break; case "phoneNumber": dispatch({ type: event.target.name, payload: event.target.value }); break; case "partyName": dispatch({ type: event.target.name, payload: event.target.value }); break; case "userImage": dispatch({ type: event.target.name, payload: event.target.value }); setImage(URL.createObjectURL(event.target.files![0])); console.log(uploadState); break; default: return uploadState; } }; return ( <> <div className={UploadStyle.container}> <h2 className={CommonStyle.header} style={{marginTop: "1rem"}}>Enter Details</h2> <div className={UploadStyle.detailsSection}> <div className={UploadStyle.textSection}> <InputField type="text" name="candidateName" placeholder="Enter Name" styles={CommonStyle.commonInput} handleChange={handleChange} /> <InputField type="text" name="phoneNumber" placeholder="Enter PhoneNumber" styles={CommonStyle.commonInput} handleChange={handleChange} /> <InputField type="text" name="PartyName" placeholder="Enter Party Name" styles={CommonStyle.commonInput} handleChange={handleChange} /> </div> <div className={UploadStyle.imageSection}> <input type="file" name="imageInput" className={UploadStyle.imageInput} ref={inputRef} onChange={handleChange} /> <Image source={image} styles={UploadStyle.imageUpload} /> <Button name="Upload Image" styles={UploadStyle.button} type="button" handleSubmit={imageUpload} /> </div> </div> <Button name="Submit" styles={CommonStyle.button} type="button" handleSubmit={handleClick}/> </div> </> ); }
Reducer代码
import { UserType } from "./Upload"; export const intionalUploadState: UserType = { name: "", phoneNumber: "", partyName: "", userImage: "", }; type UploadStateType = { type: "name" | "phoneNumber" | "partyName" | "userImage"; payload: string; }; export const uploadReducer = ( state: UserType, action: UploadStateType ) => { switch (action.type) { case "name": return { ...state, name: action.payload }; case "phoneNumber": return { ...state, phoneNumber: action.payload }; case "partyName": return { ...state, partyName: action.payload }; case "userImage": return { ...state, userImage: action.payload }; default: return state; } };
错误原因与修复方案
1. 修复handleClick中的语法与逻辑错误
原代码中的setUser回调存在多个问题:
- 无效的可选链语法
...context.user? - 数组方法拼写错误
concate(正确应为concat) - 错误依赖
context.user而非prev参数(React状态更新需依赖prevState保证最新值)
修复后的handleClick:
const handleClick = (event: React.MouseEvent) => { event.preventDefault(); // 直接将uploadState添加到prev数组末尾,创建新数组 context?.setUser(prev => [...prev, uploadState]); };
如果需要避免引用问题,可复制uploadState对象:
const handleClick = (event: React.MouseEvent) => { event.preventDefault(); context?.setUser(prev => [...prev, {...uploadState}]); };
2. 修复InputField的name属性不匹配
原组件中InputField的name与reducer的type不匹配,导致无法正确更新uploadState:
- 将第一个InputField的
name="candidateName"改为name="name" - 将第三个InputField的
name="PartyName"改为name="partyName"
修复后的代码片段:
<InputField type="text" name="name" placeholder="Enter Name" styles={CommonStyle.commonInput} handleChange={handleChange} /> <!-- 中间代码省略 --> <InputField type="text" name="partyName" placeholder="Enter Party Name" styles={CommonStyle.commonInput} handleChange={handleChange} />
3. 修复文件输入框的name属性不匹配
原文件输入框的name="imageInput"与handleChange中判断的userImage不匹配,导致无法更新uploadState.userImage:
<input type="file" name="userImage" className={UploadStyle.imageInput} ref={inputRef} onChange={handleChange} />
额外优化建议
- 添加表单验证:在
handleClick中检查uploadState的字段是否为空,避免添加无效用户数据 - 重置上传状态:添加用户后,可在reducer中新增重置action,将
uploadState恢复为初始值,方便下次输入
内容的提问来源于stack exchange,提问作者Kapil
相关产品推荐
相关产品推荐

