自定义Hook结合localStorage存储next/image组件失败求助
解决方案:存储图片元数据而非React元素
问题根源
localStorage仅支持存储JSON可序列化的数据(字符串、数字、普通对象/数组),你当前尝试存储的<Image>是React元素对象,包含$$typeof: Symbol(react.element)这类无法被JSON序列化的特殊字段,因此存入后无法正常读取还原。
具体修改步骤
1. 调整Votepage组件:存储图片元数据而非React元素
将状态从存储React元素改为存储选中的voteIcon元数据(普通可序列化对象):
// Votepage组件 import { useRouter } from "next/router"; import styled from "styled-components"; import { useState } from "react"; import { StyledBackLink } from "@/components/styles/BackLink"; import VoteDetails from "@/components/VoteDetails"; import { voteIcons } from "@/Icons/dataIcons/"; import Image from "next/image"; function Votepage({ entryData, onHandleUpdateVoteEvent }) { // 改为存储选中的voteIcon对象,而非React元素 const [selectedVoteIcon, setSelectedVoteIcon] = useState(null); const router = useRouter(); const { id } = router.query; const currentEvent = entryData.find((entryToVote) => entryToVote.id === id); function handleVoteResult() { const resultVoteEvent = { ...currentEvent, // 存储元数据对象 voteResult: selectedVoteIcon, }; onHandleUpdateVoteEvent(resultVoteEvent); } return ( <> <StyledMain> <StyledBackLink href="/">Home</StyledBackLink> <StyledVoteTitle>Voting</StyledVoteTitle> <StyledVoteEventCard> <VoteDetails // 传递元数据,在VoteDetails内部渲染Image selectedVoteIcon={selectedVoteIcon} currentEvent={currentEvent} /> <StyledEmojiCheckmark> {/* 用元数据渲染Image组件 */} {selectedVoteIcon && ( <Image width={50} height={50} src={selectedVoteIcon.imageSrc} alt={selectedVoteIcon.description} /> )} </StyledEmojiCheckmark> </StyledVoteEventCard> <StyledVoteButtonContainer> {voteIcons.map((voteIcon) => ( <StyledVoteButtons key={voteIcon.id} // 点击时存储voteIcon元数据 onClick={() => setSelectedVoteIcon(voteIcon)} > <Image width={80} height={80} src={voteIcon.imageSrc} alt={voteIcon.description} /> </StyledVoteButtons> ))} </StyledVoteButtonContainer> <StyledButtonConfirm type="button" onClick={handleVoteResult}> Confirm </StyledButtonConfirm> </StyledMain> </> ); }
2. 调整VoteDetails组件(适配元数据)
如果VoteDetails之前直接接收voteCheckmarkImage渲染,现在需要改为接收selectedVoteIcon并内部生成Image:
// VoteDetails组件示例 import Image from "next/image"; function VoteDetails({ selectedVoteIcon, currentEvent }) { return ( <div> {/* 原有组件内容 */} {selectedVoteIcon && ( <Image width={50} height={50} src={selectedVoteIcon.imageSrc} alt={selectedVoteIcon.description} /> )} </div> ); }
3. 验证存储逻辑
现在voteResult存储的是普通对象(包含imageSrc、description、id等字段),可被Immer和localStorage正常序列化与存储。当从localStorage读取entryData后,只需用存储的元数据重新渲染<Image>即可。
补充优化建议
- 若想进一步减少存储体积,可仅存储
voteIcon.id,之后通过voteIcons.find(icon => icon.id === storedId)找回完整元数据。 - 所有存入localStorage的数据,必须是
JSON.stringify可处理的类型,避免存储函数、Symbol、React元素、类实例等复杂对象。
内容的提问来源于stack exchange,提问作者hossi
相关产品推荐
相关产品推荐

