React事件提交后创建者名称显示Unknown问题求助
React事件详情页创建者显示“Unknown”问题排查与修复
问题描述
开发React事件添加应用,表单包含用户选择下拉菜单,填写信息后通过POST请求提交到http://localhost:3000/events,事件能成功创建并在列表中显示,但进入详情页后,创建者名称始终显示为“Unknown”,推测提交时用户信息未正确传递。
相关代码
表单组件代码
export const loader = async ({ params }) => { const categories = await fetch("http://localhost:3000/categories") const users = await fetch("http://localhost:3000/users") const event = await fetch("http://localhost:3000/events") return { event: await event.json(), categories: await categories.json(), users: await users.json() } } export const FormPage = () => { const [selectedCategories, setSelectedCategories] = useState([]) const [selectedUser, setSelectedUser] = useState("") // 用户选择状态 const [title, setTitle] = useState("") const [description, setDescription] = useState("") const [startTime, setStartTime] = useState(0) const [endTime, setEndTime] = useState(0) const [image, setImage] = useState("") //const [location, setLocation] = useState("") const [isPending, setIsPending] = useState(false) const navigate = useNavigate() const toast = useToast() const { categories, event, users } = useLoaderData() const showToast = () => { toast({ title: "提交成功", description: "新事件已添加", duration: 3000, isClosable: true, status: "success", position: "top" }) } const handleChange = e => { setSelectedUser(e.target.value) } const handleSubmit = async e => { e.preventDefault() const addEvent = { title: title, createdBy: selectedUser, // 下拉选择的用户ID description: description, startTime: startTime, endTime: endTime, image: image, categoryIds: [] } addEvent.categoryIds = selectedCategories setIsPending(true) try { fetch("http://localhost:3000/events", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(addEvent) }) setIsPending(false) showToast() navigate("/") if (response.ok) { alert("资源更新成功") navigate("/") } else { alert("资源更新失败") } } catch (error) { console.error("错误:", error) } } return ( <Box> <AbsoluteCenter> <Card> <form onSubmit={handleSubmit}> <CardBody> <div className="container-body"> <p style={{ marginTop: "40px", marginLeft: "5px" }}>标题:</p> <input type="text" name="title" onChange={e => setTitle(e.target.value)} className="input-form" /> <p style={{ marginLeft: "5px" }}>描述:</p> <textarea name="description" onChange={e => setDescription(e.target.value)} className="textarea-form"></textarea> <FilterBar activeCategories={selectedCategories} setActiveCategories={setSelectedCategories} categories={categories} /> <input type="file" name="image" id="fileInput" accept="image/*" onChange={handleFileChange} /> {/* 问题中的下拉菜单 */} <div> <select onChange={handleChange} id="createdBy" value={selectedUser} required className="dropdown"> {users.map(user => ( <option key={user.id} value={user.id}> {user.name} </option> ))} </select> </div> <div className="container-date"> <div className="date-start"> <span>开始时间:</span> <input className="input-date" type="datetime-local" onChange={e => setStartTime(e.target.value)} /> <br></br> </div> <div> <span>结束时间:</span> <input className="input-date" type="datetime-local" onChange={e => setEndTime(e.target.value)} /> </div> </div> </div> </CardBody> <Divider /> <CardFooter className="footer-form"> {!isPending && <CButton type="submit">提交</CButton>} {isPending && <CButton>添加事件中...</CButton>} </CardFooter> </form> </Card> </AbsoluteCenter> </Box> ) }
事件详情页组件代码
// 事件详情页组件 export const eventDetailsLoader = async ({ params }) => { const event = await fetch(`http://localhost:3000/events/${params.eventId}`) const categories = await fetch("http://localhost:3000/categories") const users = await fetch("http://localhost:3000/users") return { event: await event.json(), categories: await categories.json(), users: await users.json() } } export const EventPage = () => { const { event, categories, users } = useLoaderData() const categoryIds = Array.isArray(event.categoryIds) ? event.categoryIds : [] const categoryNames = categoryIds.map(id => categories.find(category => category.id === id)?.name || "Unknown") const reverseString = date => { const splitDate = date.split("-") const reverseArray = splitDate.reverse() const joinArray = reverseArray.join("-") return joinArray } const user = users.find(user => user.id === event.createdBy) || {} const finalEvent = { ...event, date: reverseString((event.startTime || "").slice(0, 10).toString() || ""), startTime: event.startTime ? event.startTime.split("T")[1]?.slice(0, 5).toString() : "", endTime: event.endTime ? event.endTime.split("T")[1]?.slice(0, 5).toString() : "", categoryNames: categoryNames, userName: user.name || "Unknown", userImage: user.image || "DefaultImageURL" } const text = (label, content) => ( <Flex> <Text fontStyle="italic" fontWeight="bold"> {label} {":"} </Text> <Text style={{ marginLeft: "30px" }}>{content}</Text> </Flex> ) const listItems = items => ( <List> {items.map((item, index) => ( <ListItem key={index}>{item}</ListItem> ))} </List> ) return ( <Center display="flex" flexDir="column"> <Card minW={450} h="full" mt={300}> <CardHeader fontWeight="bold"> <h1>{finalEvent.title}</h1> <CardHeader m={0} p={0}> <Flex flexDir="column" color="white"> <Image src={finalEvent.image} w="75%" h="30em" /> </Flex> </CardHeader> </CardHeader> <CardBody align="center"> {text("活动内容", finalEvent.description)} {text("日期", finalEvent.date)} {text("时间", `${finalEvent.startTime} - ${finalEvent.endTime}h`)} {text("地点", finalEvent.location)} </CardBody> <hr /> <CardFooter pl={-5} pr={0}> <Flex w="100%"> <Box w="50%"> <Tag size="lg" borderRadius="full" bgColor="white"> <Avatar src={finalEvent.userImage} size="md" name={finalEvent.userName} ml={3} mr={3} /> <TagLabel font={9}> {finalEvent.userName}</TagLabel> </Tag> </Box> <Spacer /> <Box w="16.5%"></Box> <Spacer /> <Spacer /> <Box w="16.5%"> <Link to="/"> <Button colorScheme="purple" size="l" padding={4}> 返回 </Button> </Link> </Box> </Flex> </CardFooter> </Card> </Center> ) }
问题排查与修复方案
1. 修复表单提交逻辑的响应处理错误
表单的handleSubmit函数中,fetch调用未等待响应,且response变量未定义,导致不管请求成功与否都会直接跳转。修改如下:
const handleSubmit = async e => { e.preventDefault() const addEvent = { title: title, createdBy: selectedUser, description: description, startTime: startTime, endTime: endTime, image: image, categoryIds: selectedCategories } setIsPending(true) try { // 等待fetch响应 const response = await fetch("http://localhost:3000/events", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(addEvent) }) if (response.ok) { setIsPending(false) showToast() alert("资源更新成功") navigate("/") } else { setIsPending(false) alert("资源更新失败") } } catch (error) { setIsPending(false) console.error("错误:", error) alert("提交失败,请重试") } }
2. 修复用户ID类型不匹配问题
下拉菜单的value默认是字符串类型,若后端存储的user.id是数字类型,详情页中users.find(user => user.id === event.createdBy)会因类型不匹配返回undefined,导致显示“Unknown”。
方案一:提交时转换为数字
修改表单中addEvent的createdBy字段:
createdBy: Number(selectedUser),
方案二:详情页匹配时忽略类型
修改详情页中查找用户的逻辑:
const user = users.find(user => user.id == event.createdBy) || {}
3. 补充缺失的handleFileChange函数
表单中文件输入框绑定了handleFileChange但未定义,会导致图片上传功能失效,补充该函数:
const handleFileChange = e => { const file = e.target.files[0] if (file) { const reader = new FileReader() reader.onloadend = () => { setImage(reader.result) } reader.readAsDataURL(file) } }
验证步骤
- 修复代码后重新启动应用
- 创建新事件并选择用户
- 进入事件详情页,确认创建者名称正常显示
内容的提问来源于stack exchange,提问作者ECode
相关产品推荐
相关产品推荐

