React Native 如何实现todo列表点击单个图标后实时更新视图
你遇到的问题本质是直接修改props传入的引用类型数据,没有触发React的重渲染机制导致的。React组件的视图更新依赖状态变更触发,直接修改对象属性的操作不会被React感知,只有当组件重新挂载(比如你关闭modal再打开)或者接收新的props时,才会重新读取数据渲染视图,这就是你之前只有重新打开modal才看到新图标的原因。
以下是两种常用解决方案:
方案1:todos状态由父组件维护(推荐,适合需要同步todo修改到上层的场景)
父组件需要传递修改todos的方法到当前组件,你可以通过调用这个方法触发父组件的状态更新,进而带动当前组件重渲染:
- 父组件代码示例:
// 父组件中维护todos状态和更新方法 import { useState } from 'react'; import TeacherMessages from './TeacherMessages'; const ParentComponent = () => { const [todos, setTodos] = useState([/* 你的初始todo列表 */]); // 不可变更新todo的选中状态 const toggleTodoCheck = (todoId) => { setTodos(prevTodos => prevTodos.map(todo => todo.id === todoId ? {...todo, isChecked: !todo.isChecked} : todo )); }; return <TeacherMessages todos={todos} onToggleTodo={toggleTodoCheck} /> }
- 你的
TeacherMessages组件修改如下:
export const TeacherMessages = (props) => { return ( <View style={[ styles.borderBox, props.todos.length > 0 || props.notes.length > 0 ? styles.whiteBox : null, ]} > { props.todos.map((todo) => ( <View key={todo.id} style={styles.listNotes}> <AntDesign style={styles.listIcon} onPress={() => props.onToggleTodo(todo.id)} name={todo.isChecked ? "checksquare" : "exclamationcircle"} color={todo.isChecked ? "green" : "red"} size={18} /> <Text style={styles.listText}> {todo.description}</Text> </View> )) } </View> ); }
方案2:todos状态由当前组件内部维护(适合不需要同步修改到上层的场景)
如果不需要把todo的修改结果同步给父组件,你可以直接在当前组件内部把传入的todos转为本地状态维护:
import { useState } from 'react'; export const TeacherMessages = (props) => { // 初始化本地状态,值为props传入的todos const [localTodos, setLocalTodos] = useState(props.todos); const toggleTodoCheck = (todoId) => { setLocalTodos(prev => prev.map(todo => todo.id === todoId ? {...todo, isChecked: !todo.isChecked} : todo )); }; return ( <View style={[ styles.borderBox, props.todos.length > 0 || props.notes.length > 0 ? styles.whiteBox : null, ]} > { localTodos.map((todo) => ( <View key={todo.id} style={styles.listNotes}> <AntDesign style={styles.listIcon} onPress={() => toggleTodoCheck(todo.id)} name={todo.isChecked ? "checksquare" : "exclamationcircle"} color={todo.isChecked ? "green" : "red"} size={18} /> <Text style={styles.listText}> {todo.description}</Text> </View> )) } </View> ); }
原问题参考图:

内容的提问来源于stack exchange,提问作者theodorn
相关产品推荐
相关产品推荐

