简体   繁体   中英

Unable to populate option elements to select element using array.map()

I'm getting an array of vehicle makes from an api, and trying to map each item in the array to an option element within a select element:

  const Makes = () => {   
    return (
      <select aria-label="Select a make">
        {/* Populate with option elements based on the years state and its index */}
        <option value="">Select a make</option>
        {makes.map((make) => <option key={make.toString()} value={make}>test</option>)}
      </select>
    );
  };

makes is defined in the upper scope as an empty array, and I'm filling the array with a fetchMakesByYear function that looks like this:

  const fetchMakesByYear = async () => {
    const url = `https://www.fueleconomy.gov/ws/rest/vehicle/menu/make?year=${year}`;

    const headers = {
      headers: {
        'Content-Type': 'application/xml',
        Accept: 'application/xml',
      },
    };

    try {
      const data = await fetch(url, headers);
      const itemUnformatted = await data.text();
      const makesByYearUnformatted = convert.xml2js(itemUnformatted, { compact: true, spaces: 2 });
      const makesByYear = makesByYearUnformatted.menuItems.menuItem;

      for (let i = 0; i < makesByYear.length; i += 1) {
        makes.push(makesByYear[i].text._text);
      }
    } catch (err) {
      console.log(err);
    }
  };

  useEffect(() => {
    fetchMakesByYear();
  });

Not sure why the options are not being populated. Any ideas on what I'm doing wrong here? Thanks.

Use state to store the makes array and update it on fetch which will re render your component and useEffect to call your fetchMakesByYear on component mount.

Infinite render is because you have not passed dependency array in useEffect , so it calls it on every render.

const [makes,setMakes] = useState([]) // use state to hold your array

const fetchMakesByYear = useCallback(async () => { // use useCallback hook to wrap your function so that this function is not created on every render and hence doesn't call useEffect as we will be giving it as a dependency
    const url = `https://www.fueleconomy.gov/ws/rest/vehicle/menu/make?year=${year}`;

    const headers = {
      headers: {
        'Content-Type': 'application/xml',
        Accept: 'application/xml',
      },
    };

    try {
      const data = await fetch(url, headers);
      const itemUnformatted = await data.text();
      const makesByYearUnformatted = convert.xml2js(itemUnformatted, { compact: true, spaces: 2 });
      const makesByYear = makesByYearUnformatted.menuItems.menuItem;

      for (let i = 0; i < makesByYear.length; i += 1) {
        makes.push(makesByYear[i].text._text);
      }
      setMakes(makes) // set state to update your array in the state
    } catch (err) {
      console.log(err);
    }
},[]);

useEffect(()=>{
  fetchMakesByYear()
},[fetchMakesByYear]) // add dependency in useEffect here

return (
   {Makes()}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM