React Native问题:点击标签后视图不随状态变更更新样式
解决React Native标签选中后样式不即时更新问题
在类Tinder的React Native应用中,点击标签选中后,标签的背景色不会立刻变化,只有组件刷新(比如修改代码触发热重载)时,选中的标签才会显示正确的高亮样式。
原问题代码
const [selectedItems, setSelectedItems] = useState([]); const addItem = (id) => { console.log(id); if(selectedItems.includes(id)) { let index = selectedItems.findIndex(interest => interest == id); if(index > -1) { let selectedInterests = selectedItems; selectedInterests.splice(index, 1) setSelectedItems(selectedInterests); } } else { if(selectedItems.length < 10) { let selectedInterests = selectedItems; selectedInterests.push(id); setSelectedItems(selectedInterests); } } }; {root.userStore.tags.map((item,index) => {return ( <Text key={item.id} onPress={()=>{ addItem(item.id) }} style={{ fontSize:17, padding:6, paddingLeft:10, paddingRight:10, ...selectedItems.includes(item.id) ? { color:'white', borderColor:'#E13545',backgroundColor:'#E13545' } : { color:'rgb(100,100,100)',borderColor:'rgba(0,0,0,0.1)',backgroundColor:'white' }, borderRadius:35, borderWidth:1, margin:5 }}>{I18n.t(item.title)}</Text> )})}
问题原因
问题出在修改selectedItems数组的方式上:
let selectedInterests = selectedItems;这行代码只是创建了原数组的引用,并没有生成新数组- 后续的
splice或push操作都是直接修改原数组,而React的useState只有在传入的state值引用发生变化时,才会触发组件重新渲染 - 因为原数组引用没变,组件不会更新,所以样式也不会即时变化
修复后的代码
通过创建原数组的副本(使用扩展运算符[...selectedItems]或slice()),修改副本后再更新state,就能触发组件重新渲染:
const [selectedItems, setSelectedItems] = useState([]); const addItem = (id) => { console.log(id); if(selectedItems.includes(id)) { // 创建原数组的副本,过滤掉当前id const updatedItems = selectedItems.filter(item => item !== id); setSelectedItems(updatedItems); } else { if(selectedItems.length < 10) { // 创建新数组,添加当前id const updatedItems = [...selectedItems, id]; setSelectedItems(updatedItems); } } }; {root.userStore.tags.map((item,index) => {return ( <Text key={item.id} onPress={()=>{ addItem(item.id) }} style={{ fontSize:17, padding:6, paddingLeft:10, paddingRight:10, ...selectedItems.includes(item.id) ? { color:'white', borderColor:'#E13545',backgroundColor:'#E13545' } : { color:'rgb(100,100,100)',borderColor:'rgba(0,0,0,0.1)',backgroundColor:'white' }, borderRadius:35, borderWidth:1, margin:5 }}>{I18n.t(item.title)}</Text> )})}
说明
- 使用
filter方法删除元素,会返回一个新数组,避免直接修改原数组 - 使用扩展运算符
[...selectedItems, id]创建新数组并添加元素,保证state引用更新 - 这样每次点击标签时,state都会得到一个新的数组引用,触发组件重新渲染,选中状态的样式就能即时生效
内容的提问来源于stack exchange,提问作者gabogabans
相关产品推荐
相关产品推荐

