React Native中@ui-kitten/components的Select组件选择卡顿延迟问题
问题根因
- 冗余状态导致多次重渲染:你单独维护了
selectedIndex本地状态,选中时同时触发本地state更新和Formik的setFieldValue更新,两次状态更新会触发至少两次组件重渲染,若表单整体复杂度高,重渲染耗时会被放大。 - 回调函数未做缓存:
renderOption方法、label属性的匿名渲染函数每次组件渲染时都会重新生成新的实例,导致Select组件被频繁触发不必要的重渲染。 - Formik默认校验机制消耗性能:
setFieldValue默认会触发表单全量校验,如果你配置了表单校验规则,每次选中都会跑一次全量校验逻辑,表单字段多的话会产生明显延迟。 - 取值逻辑错误(非延迟直接原因但需要修复):
setSelectedIndex是异步更新,你紧接着取的displayValue是更新前的旧值,会导致表单提交的语言和实际选中值不一致。
可行优化方案
- 移除冗余本地状态,直接绑定Formik的值,减少状态更新次数
- 用
useCallback缓存渲染函数和回调,避免不必要的组件重渲染 - 调用
setFieldValue时关闭即时校验,只在提交时触发校验 - 复杂表单场景下使用Formik的
FastField减少跨字段重渲染影响 - 开发环境debug模式本身存在性能损耗,可打release包确认是否是生产环境也存在延迟,排除debug工具的额外开销影响
优化后代码示例
import { useCallback } from 'react'; import { useFormikContext } from 'formik'; import { Select, SelectItem, Text, IndexPath } from '@ui-kitten/components'; // 常量移到组件外部,避免每次渲染重新生成 const languageData = ['Select language', 'English', 'Hindi']; // 业务组件内代码 const { values, setFieldValue } = useFormikContext(); // 用useCallback缓存渲染函数 const renderOption = useCallback((title) => <SelectItem title={title} key={title} />, []); const renderLabel = useCallback((evaProps) => <Text {...evaProps}>Native language</Text>, []); // 计算当前选中的索引 const selectedIndex = new IndexPath(languageData.findIndex(item => item === values.language)); const handleSelect = useCallback((index) => { const selectedLang = languageData[index.row]; // 第三个参数传false关闭本次更新的校验触发 setFieldValue('language', selectedLang, false); }, [setFieldValue]); // Select组件调用 <Select value={values.language} selectedIndex={selectedIndex} onSelect={handleSelect} label={renderLabel} > {languageData.map(renderOption)} </Select>
内容的提问来源于stack exchange,提问作者Surbhi Davara
相关产品推荐
相关产品推荐

