React Native如何创建全局状态?解决收藏夹点击后页面不重渲染问题
问题核心原因
- 直接突变了来自
StorageContext的storageDB对象:React 依赖状态引用变化判断是否触发重渲染,你直接修改原对象的favorite属性,storageDB的引用没有变更,所有监听它的组件/钩子都感知不到更新 useStorage中获取收藏列表的逻辑只在钩子初始化时执行一次,没有和全局的storageDB状态绑定- 调用
storage.storeData只更新了本地持久化存储,没有同步更新StorageContext里的全局状态
修复步骤
1. 调整toggleFavorite逻辑,做不可变更新并同步全局状态
首先要用到你封装的全局setStorageDB方法,修改时生成全新的storageDB对象,不要直接修改原对象:
const useStorage = (name, id, pratice, navigation) => { // 先从context取出状态更新方法 const { storageDB, setStorageDB } = useContext(StorageContext); const toggleFavorite = () => { // 生成全新的storageDB副本做修改,避免突变原状态 const newStorageDB = [...storageDB]; const currentTopicIndex = topicIndex(); // 生成当前分类的练习数组副本 const newExercises = [...newStorageDB[currentTopicIndex].exercises]; const exerciseIndex = newExercises.findIndex(ex => ex.id === id); // 生成目标练习的副本并修改favorite属性 const targetExercise = { ...newExercises[exerciseIndex], favorite: !newExercises[exerciseIndex].favorite }; newExercises[exerciseIndex] = targetExercise; newStorageDB[currentTopicIndex].exercises = newExercises; // 同步更新全局context状态,触发所有依赖的组件重渲染 setStorageDB(newStorageDB); // 再更新本地持久化存储 storage.storeData(newStorageDB); }; // 其他逻辑... }
2. 调整useStorage的收藏列表计算逻辑,和storageDB绑定
把原来的useEffect触发getFavorites改成用useMemo自动计算,只要storageDB变了就自动更新收藏列表:
const useStorage = (name, id, pratice, navigation) => { const { storageDB, setStorageDB } = useContext(StorageContext); // 移除原来的favorites状态和对应的getFavorites useEffect逻辑 const favorites = useMemo(() => { const checkFavorites = storageDB.map((store) => store.exercises.filter((exArray) => exArray.favorite) ); const favoritesResult = checkFavorites.filter((ex) => ex.length !== 0); return favoritesResult.length ? favoritesResult : null; }, [storageDB]); // storageDB变化时自动重新计算 const toggleFavorite = () => { /* 上面的逻辑 */ } return { storageDB, toggleFavorite, favorites }; }; export default useStorage;
3. 确认StorageContext的状态更新逻辑正常
要保证setStorageDB是标准的React状态更新方法,是你在定义StorageContext时通过useState声明的:
// 示例StorageContext Provider的逻辑 const StorageProvider = ({ children }) => { const [storageDB, setStorageDB = useState(/* 初始值,从AsyncStorage取或者默认值 */); // 其他初始化逻辑 return ( <StorageContext.Provider value={{ storageDB, setStorageDB }}> {children} </StorageContext.Provider> ) }
修改完成后点击收藏按钮会触发全局storageDB的引用变更,useStorage里的收藏列表会自动更新,FavoritesScreen就会跟着重渲染。
内容的提问来源于stack exchange,提问作者Marshall
相关产品推荐
相关产品推荐

