React Native中useState与useEffect配合切换分类时变量未定义问题
问题分析与解决方案
核心问题
你遇到的novelListSelection始终为undefined的原因,是错误地用useEffect处理派生状态:
useEffect回调在组件渲染完成后才执行,而渲染阶段(计算pageContents时)novelListSelection还没被赋值,所以初始值是undefined。- 即便
useEffect里给变量赋了值,由于它不是React状态变量,不会触发组件重新渲染,页面仍会沿用之前的undefined值。
修复方案
直接在渲染阶段根据novelListSelector计算novelListSelection即可——这是由现有状态派生出来的值,完全不需要useEffect:
import { ImageBackground, SafeAreaView, StyleSheet } from "react-native"; import { useState } from "react"; import { NOVELS } from "../data/dummy-data"; import NovelList from "../components/Novels/NovelList"; import NovelToggle from "../components/Novels/NovelToggle"; import NovelModal from "../components/Novels/NovelModal"; const Canon = () => { const [summaryModalOpen, setSummaryModalOpen] = useState({ isOpen: false, novelId: null, }); const [novelListSelector, setNovelListSelector] = useState("novels"); const canonNovels = NOVELS.filter((novel) => { return novel.is_graphic_novel === false && novel.is_canon === true; }); const canonGraphicNovels = NOVELS.filter((novel) => { return novel.is_graphic_novel === true && novel.is_canon === true; }); // 直接在渲染阶段计算派生值,无需useEffect let novelListSelection; if (novelListSelector === "novels") { novelListSelection = canonNovels; } else if (novelListSelector === "graphic-novels") { novelListSelection = canonGraphicNovels; } else { novelListSelection = canonNovels.concat(canonGraphicNovels); } let pageContents; if (summaryModalOpen.isOpen) { console.log("SUMMARY MODAL OPEN"); // 用find替代filter[0],避免创建不必要的数组,性能更优 const selectedNovel = NOVELS.find(novel => novel.id === summaryModalOpen.novelId); const novelModalProps = { id: selectedNovel.id, title: selectedNovel.title, authors: selectedNovel.authors, releaseDate: selectedNovel.release_date, summary: selectedNovel.summary, image: selectedNovel.image, isGraphicNovel: selectedNovel.is_graphic_novel, isCanon: selectedNovel.is_canon, }; pageContents = ( <NovelModal {...novelModalProps} setSummaryModalOpen={setSummaryModalOpen} /> ); } else { console.log(`NOVEL SELECTION: ${novelListSelection}`); pageContents = ( <> <NovelToggle setNovelListSelector={setNovelListSelector} /> <NovelList novels={novelListSelection} setSummaryModalOpen={setSummaryModalOpen} /> </> ); } return ( <SafeAreaView style={styles.wrapper}> <ImageBackground source={require("../assets/images/jedi_holocron.png")} style={styles.image} > {pageContents} </ImageBackground> </SafeAreaView> ); }; const styles = StyleSheet.create({ wrapper: { flex: 1, justifyContent: "center", }, image: { flex: 1, }, }); export default Canon;
额外优化说明
- 将
NOVELS.filter(...)[0]替换为NOVELS.find(...),减少不必要的数组创建,提升性能。 - 派生值直接通过普通条件判断计算,代码逻辑更直观,完全符合React状态管理的最佳实践。
内容的提问来源于stack exchange,提问作者EidoAvi
相关产品推荐
相关产品推荐

