Having trouble with useState working with useEffect in React Native App

Having trouble with useState working with useEffect in React Native App

  

I'm having an issue having my state work with a toggle to switch between categories. As far as I understand it I should be using the useEffect hook to have the page re render dependent on conditions. My 'novelListSelection' variable is coming out as undefined every time.

What I'm seeking is to click a toggle button. My state for novelListSelector to change which is working. But depending on what state it is in it will render a different set of novels or graphic novels. Here's the code:

import { ImageBackground, SafeAreaView, StyleSheet } from "react-native";
import { useEffect, 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;
  });

  let novelListSelection;

  useEffect(() => {
    if (novelListSelector === "novels") {
      novelListSelection = canonNovels;
    } else if (novelListSelector === "graphic-novels") {
      novelListSelection = canonGraphicNovels;
    } else {
      novelListSelection = canonNovels.concat(canonGraphicNovels);
    }
  }, [canonNovels, canonGraphicNovels, novelListSelector]);

  let pageContents;

  if (summaryModalOpen.isOpen) {
    console.log("SUMMARY MODAL OPEN");
    const selectedNovel = NOVELS.filter((novel) => {
      return novel.id === summaryModalOpen.novelId;
    })[0];

    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;

Is it my dependencies I'm using in useEffect that is incorrect? Is useEffect not the proper hook for this? I've tried variations on what the useEffect is dependent on. I've also tried using a switch statement as opposed to an if block chain. Thanks in advance

Answer

Having novelListSelection as a variable doesn't allow the component to re-render causing it to stay undefined. Recommend moving novelListSelection to a state variable for it to be set and rendered correctly on change.

Try something like the below in your existing code:

  const [novelListSelection, setNovelListSelection] = useState();

  useEffect(() => {
    if (novelListSelector === "novels") {
      setNovelListSelection(canonNovels);
    } else if (novelListSelector === "graphic-novels") {
      setNovelListSelection(canonGraphicNovels);
    } else {
      setNovelListSelection(canonNovels.concat(canonGraphicNovels));
    }
  }, [canonNovels, canonGraphicNovels, novelListSelector, setNovelListSelection]);
© 2024 Dagalaxy. All rights reserved.