useState初始值能否充当缓存避免重复计算?验证i18n翻译缓存实现的正确性
嘿,你的这个思路是完全正确的!咱们来拆解一下为什么这个写法能精准达到你想要的缓存翻译效果:
当你把包含translate调用的对象作为useState的初始值传入时,这个初始值的计算逻辑只会在组件首次渲染时执行一次。之后不管组件因为什么原因重渲染——比如父组件更新了props、自身其他state发生变化,useState都会直接复用之前已经存在的translations状态值,不会再重新执行初始对象的构建逻辑,自然也就不会重复调用translate函数了。
举个直观的例子,你的这段代码:
const [translations] = useState({ header: translate('translation.string.goes.here'), welcomeMessage: translate('translation.string.goes.here') });
里面的两个translate调用,只会在组件第一次挂载的时候跑一遍,后续重渲染时直接用state里已经缓存好的translations.header和translations.welcomeMessage,完全不会触发新的翻译计算,完美实现了你要的缓存效果。
不过这里要给你提个潜在的小坑:如果你的应用支持语言切换功能,那当前的写法就会出问题了!因为语言切换时,组件不会重新初始化state,translations会一直停留在旧语言的翻译结果上。这时候你需要配合useEffect监听语言变化的信号,主动更新缓存的翻译内容,比如:
const [translations, setTranslations] = useState({ header: translate('translation.string.goes.here'), welcomeMessage: translate('translation.string.goes.here') }); const { i18n } = useTranslation(); useEffect(() => { // 语言变化时重新计算翻译并更新state setTranslations({ header: translate('translation.string.goes.here'), welcomeMessage: translate('translation.string.goes.here') }); }, [i18n.language]); // 把当前语言作为依赖项,语言变化时触发
另外,你也可以用useMemo来实现类似的缓存效果,写法会更简洁一些:
const translations = useMemo(() => ({ header: translate('translation.string.goes.here'), welcomeMessage: translate('translation.string.goes.here') }), []); // 空依赖数组,只在首次渲染时计算一次
如果需要支持语言切换,只要把i18n.language加到依赖数组里就行,和useState+useEffect的组合效果一致。
总的来说,在不需要语言切换的场景下,你当前的useState写法完全可靠,能有效减少不必要的翻译计算;如果有语言切换需求,记得补充对应的更新逻辑就好。
内容来源于stack exchange

