Next.js页面刷新后开关按钮状态无法持久化问题求助
问题
在Next.js开发的配置页面中,开关按钮切换后状态可从active变为maintenance,点击保存会弹出成功提示,但刷新页面后开关会恢复为active状态。需要实现刷新页面后开关保持修改后的状态,切换回原状态时刷新也能同步对应状态。
接口返回的单条配置JSON结构:
{ "id": "d9cbf36e-bb51-11ee-a740-00155db75f50", "name": "Beranda", "code": "home", "position": 1, "is_maintenance": false }
解决方案
核心问题分析
当前代码的问题在于:
checkStatus初始化时依赖空数组config,导致初始状态为空对象,接口返回数据后未同步更新checkStatus- 保存成功后未重新拉取最新配置,虽然刷新会重新请求,但页面状态无法立即与后端同步
修改后的完整代码
import React, { useEffect, useState } from 'react' import { useRouter } from 'next/router' import { WebConfigurationType, WebConfigType } from '@/type/web' import { getData, postData, putData } from '@/utility/fetch' import { showMessage } from '@/components/alerts/showMessage'; const STATUS_COLORS = { active: 'green', maintenance: 'red', }; const STATUS_TEXT = { active: 'Aktif', maintenance: '(Maintenance)', }; const CheckboxSwitch = ({ label, name, checked, onChange }: any) => { const labelColor = checked ? STATUS_COLORS.maintenance : STATUS_COLORS.active; return ( <div className="input-banner mb-5"> <div className="mb-2 flex justify-between gap-4"> <div className="flex gap-2"> <div className="label-banner style={black}">{label}</div> <div className="label-banner" style={{ color: labelColor }}> {checked ? STATUS_TEXT.maintenance : STATUS_TEXT.active} </div> </div> <label className="relative h-6 w-12"> <input type="checkbox" className="custom_switch peer absolute z-10 h-full w-full cursor-pointer opacity-0" id={`custom_switch_checkbox_${name}`} checked={checked} onChange={onChange} name={name} /> <span className={`block h-full rounded-full bg-[#ebedf2] before:absolute before:bottom-1 before:left-1 before:h-4 before:w-4 before:rounded-full before:bg-white before:transition-all before:duration-300 peer-checked:bg-primary peer-checked:before:left-7 dark:bg-dark dark:before:bg-white-dark dark:peer-checked:before:bg-white`}></span> </label> </div> </div> ); }; function WebConfig() { const router = useRouter() const [webConfig, setWebConfig] = useState<WebConfigType>() const [config, setConfig] = useState<WebConfigurationType[]>([]) const [checkStatus, setCheckStatus] = useState<Record<string, boolean>>({}) // 统一生成checkStatus的工具函数 const generateCheckStatus = (data: WebConfigurationType[]) => { return data.reduce((acc, item) => { acc[item.name] = item.is_maintenance return acc }, {} as Record<string, boolean>) } useEffect(() => { const getDataWeb = async () => { try { const {data} = await getData('/page-configuration') setConfig(data.page_configuration) // 接口返回数据后同步更新checkStatus setCheckStatus(generateCheckStatus(data.page_configuration)) } catch (error: any) { console.error('获取配置失败:', error) } } getDataWeb() },[]) const handleChangeBox = (name: string) => { setCheckStatus(prev => ({...prev, [name]: !prev[name]})) } const generateDialog = async () => { try { await putData('/page-configuration', checkStatus) showMessage('Berhasil', 'success') // 保存成功后重新拉取最新配置,确保状态完全同步 const {data} = await getData('/page-configuration') setConfig(data.page_configuration) setCheckStatus(generateCheckStatus(data.page_configuration)) } catch (error) { showMessage('Gagal', 'error') console.error('保存配置失败:', error) } } const handleMultiplyCheck = async (ev: React.FormEvent) => { ev.preventDefault() generateDialog() } return ( <> <div className='h-full w-full p-4'> <div className='w-full h-full bg-white rounded-lg shadow-md border border-slate-200 p-3'> <div className='w-full px-4 py-3 flex justify-between items-center mb-9'> <div> <h3 className='font-semibold text-3xl'>Web Configuration</h3> </div> </div> <div className='w-full p-3 flex flex-col gap-4'> {config.map((item, index) => ( <CheckboxSwitch key={item.id || index} // 添加唯一key,符合React列表渲染规范 label={item.name} checked={checkStatus[item.name] ?? false} // 兜底处理,避免undefined onChange={() => handleChangeBox(item.name)}/> ))} <button onClick={handleMultiplyCheck} className='p-2 rounded-md bg-blue-400 text-white font-semibold' >Simpan</button> </div> </div> </div> </> ) } export default WebConfig
关键修改点说明
- 同步初始状态:在接口获取到配置数据后,调用
setCheckStatus更新状态,确保初始值与后端数据完全一致 - 保存后刷新数据:保存成功后重新拉取最新配置,让页面状态立即同步后端,无需等待刷新
- 添加兜底处理:在
checked属性中使用?? false,避免checkStatus中无对应key时出现undefined导致的渲染错误 - 规范列表渲染:给
CheckboxSwitch添加唯一key,符合React性能优化要求
内容的提问来源于stack exchange,提问作者Hovi Sohibul Wafa
相关产品推荐
相关产品推荐

