Search code examples
arraysreactjsmodal-dialogprop

React: Assigning array to variable using useState to pass into modal


I made a JSON file for the upcoming NFL season. In this component I have a working fetch method that gets my data, and I've named the variable "squads". Now I want to press a button to filter out the selected team's schedule and display it in a modal. I've hard coded my button in this example. My modal component works fine, and I have {props.children} in the modal's body to accept my data.

In the code below you'll see that I'm trying to assign the filtered team to the selectedTeam variable using useState. The error message I'm getting just says my variables are undefined.

import React, { useState, useEffect } from "react";
import Modal from "./Components/Modal";

export default function App() {
  const [show, setShow] = useState(false);
  const [title, setTitle] = useState("");
  const [squads, setSquads] = useState([]);
  const [modalTitleBackground, setModalTitleBackground] = useState("");
  const [image, setImage] = useState("");
  const [selectedTeam, setSelectedTeam] = useState([]);

  const url = "../nfl2021.json";

  const fetchData = async () => {
    try {
      const response = await fetch(url);
      const data = await response.json();
      setSquads(data.teams);
    } catch (error) {
      console.log(error);
    }
  };

  useEffect(() => {
    fetchData();
  }, []);

  // const filterTeam = (team) => {
  //   const theTeam = squads.filter((squad) => squad.name === team);
  //   setModalTitleBackground(theTeam[0].topBG);
  //   // setTitle(theTeam[0].name);
  //   setNickname(theTeam[0].nickname);
  //   setImage(`./images/${theTeam[0].img}`);
  //   setShow(true);
  // };

  const filterTeam = (team) => {
    setSelectedTeam(squads.filter((squad) => squad.name === team));
    console.log(selectedTeam);
    setTitle(selectedTeam[0].name);
    setModalTitleBackground(selectedTeam[0].topBG);
    setImage(`./images/${selectedTeam[0].img}`);
    setShow(true);
  };

  return (
    <div className="App">
      <button onClick={() => filterTeam("New England Patriots")}>
        Show Modal
      </button>
      <button onClick={() => filterTeam("Green Bay Packers")}>
        Show Modal 2
      </button>
      <button onClick={() => filterTeam("Cincinnati Bengals")}>
        Show Modal 3
      </button>
      <Modal
        image={image}
        title={title}
        backgroundColor={modalTitleBackground}
        onClose={() => setShow(false)}
        show={show}
      >
        <p>
          This is the modal body using props.children in the modal component.
        </p>
        <p>The {title} 2021 schedule.</p>

        {selectedTeam[0].schedule.map((schedule, index) => {
          return (
            <p>
              Week {index + 1}: The {selectedTeam[0].nickname} play the{" "}
              {selectedTeam[0].schedule[index].opponent}.
            </p>
          );
        })}
      </Modal>
    </div>
  );
}


Solution

  • 1- In react, the state is set asynchronously. selectedTeam is not set until next render.

    2- You can use find instead of filter and get rid of array access.

    const [selectedTeam, setSelectedTeam] = useState({schedule: []});
    

    ...

    const filterTeam = (team) => {
        let temp = squads.find((squad) => squad.name === team);
        setSelectedTeam(temp);
        console.log(temp);
        setTitle(temp.name);
        setModalTitleBackground(temp.topBG);
        setImage(`./images/${temp.img}`);
        setShow(true);
    };
    

    ...

        {selectedTeam.schedule.map((match, index) => {
          return (
            <p>
              Week {index + 1}: The {selectedTeam.nickname} play the {match.opponent}.
            </p>
          );
        })}