React字体大小调整组件localStorage初始化取值异常问题求助
问题原因
- state类型不统一:初始给
useState传的是数字类型的defaultFont,但后续所有setFontSize调用都传入{fontSize: 数值}的对象类型,导致后续字体大小对比、样式拼接逻辑全部异常。 getTextSize逻辑完全错误:React的setState类方法都是无返回值的异步函数,你将setFontSize的返回值赋值给fontSize变量,拿到的只会是undefined,parseInt转换后就是NaN,自然无法拿到正确值。此外else分支中你给setFontSize传入的fontSize是刚定义未赋值的变量,值为undefined。- localStorage类型未转换:localStorage中存储的所有值都是字符串类型,直接读取后做数值运算会出现类型错误。
- 初始化时机过晚:你等到useEffect执行才读取localStorage赋值,其实可以直接把初始化逻辑放到
useState的入参函数中,组件挂载第一时间就能拿到正确值。
修复后完整代码
import React, { useState, useEffect, useCallback } from "react"; import PropTypes from "prop-types"; const TextResizer = ({ defaultFont, step, min, max, suffix, store, storeKey }) => { // 初始化时直接读取localStorage,转成数字,不存在则用默认值 const [fontSize, setFontSize] = useState(() => { if (store && store.getItem(storeKey)) { const savedSize = parseInt(store.getItem(storeKey), 10); // 加边界判断,避免存储的值超出min/max范围 return isNaN(savedSize) ? defaultFont : Math.min(Math.max(savedSize, min), max); } return defaultFont; }); const toggle = useCallback((type) => { let newFontSize = fontSize; switch (type) { case "increase": newFontSize = Math.min(fontSize + step, max); break; case "decrease": newFontSize = Math.max(fontSize - step, min); break; default: newFontSize = defaultFont; break; } setFontSize(newFontSize); store.setItem(storeKey, newFontSize); }, [fontSize, step, min, max, defaultFont, store, storeKey]); // 字体大小变化时同步更新全局样式 useEffect(() => { document.documentElement.style.fontSize = `${fontSize}${suffix}`; }, [fontSize, suffix]); return ( <React.Fragment> <button disabled={fontSize <= min} onClick={() => toggle("decrease")}> decrease </button> <button onClick={() => toggle("default")}>default</button> <button disabled={fontSize >= max} onClick={() => toggle("increase")}> increase </button> </React.Fragment> ); }; TextResizer.propTypes = { defaultFont: PropTypes.number, step: PropTypes.number, min: PropTypes.number, max: PropTypes.number, suffix: PropTypes.string, store: PropTypes.object, storeKey: PropTypes.string }; TextResizer.defaultProps = { defaultFont: 100, step: 20, min: 60, max: 180, suffix: "%", store: typeof window !== 'undefined' ? window.localStorage : null, storeKey: "TextResizer" }; export default TextResizer;
额外优化说明
- 用useCallback缓存toggle函数,避免不必要的重渲染
- 把全局样式更新单独放到useEffect中,逻辑更清晰,避免每次渲染都插入新的style标签
- 存储默认值增加了服务端渲染兼容判断,避免SSR场景下找不到window报错
- 加减字体时直接做边界限制,避免存储超出范围的数值
内容的提问来源于stack exchange,提问作者Digital Legend
相关产品推荐
相关产品推荐

