You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 05:00:12