Search code examples
reactjsduplicatesaxiosreact-hooksdropdown

React Hooks with Axios, updating state with no duplicates for drop down list


I am new to react hooks and fairly new to react. I am trying to generate a dropdown list that pulls values from my server. I am having trouble removing the duplicates from the list. This code probably needs a lot of re working but any help would be appreciated. I include the songform.js below and I will add what my mongodb information looks like.

SONGFORM.JS

import React, { useState, useEffect } from "react";
import axios from "../../axios-orders";

import useDropdown from '../../components/dropdown/Dropdown';

const SongForm = (props => {
  const [mood_list, setMood] = useState([]);
  const [genre_list, setGenre] = useState([]);
  const [items, setItems] = useState([]);
  const [enteredSong, setEnteredSong] = useState('');
  const [selectedGenre, GenreDropdown] = useDropdown('Genre', 'empty', genre_list);
  const [selectedMood, MoodDropdown] = useDropdown('Mood', 'empty', mood_list);

  useEffect(() => {
    const fetchData = async () => {
      let response = await axios.get('/api/songs')
      setItems(response.data.songs);
    }
    fetchData();
  }, []);

  let i = 0;
  for (i = 0; i < items.length; i++) {
    genre_list.push(items[i].genre)
  }

  let j = 0;
  for (j = 0; j < items.length; j++) {
    mood_list.push(items[j].mood)
  }

  const submitHandler = (event) => {
    event.preventDefault();
    props.filterSongs({
      genre: selectedGenre,
      mood: selectedMood,
      songSearch: enteredSong,
    });
  };

  return (
    <div className="filter-page">
      <form onSubmit={submitHandler}>

        {/* Search Filter */}

        <div className="centered-flex-container">
          <h1>Search By Name:</h1>
          <input
            className='searchbar'
            type="text"
            id="songInput"
            value={enteredSong}
            onChange={event => {
              setEnteredSong(event.target.value);
            }}
          />
          <hr></hr>
        </div>

        <div className='centered-flex-container'>
          <h1>Search By Filter:</h1>
          <GenreDropdown />
        </div>

        <div className='centered-flex-container'>
          <MoodDropdown />
        </div>

        <div className='centered-flex-container'>
          <button
            className='dark-button'
            type="submit"
          >
            Submit
        </button>
        </div>
      </form>
    </div>
  )
});

export default SongForm;

IMPORTED DATA FROM AXIOS AND MONGODB

console.log(response.data.songs) shows

(5) [{…}, {…}, {…}, {…}, {…}]

0:
audio: "midwest_money.mp3"
genre: "Rap/Hip-Hop"
id: "5edd0cdc38cb55332ccbd8f6"
mood: "Relaxed"
name: "Midwest Money"
_id: "5edd0cdc38cb55332ccbd8f6"
__proto__: Object

1: {_id: "5edd0cdc38cb55332ccbd8f2", name: "Invincible", genre: "Electronic/Pop", mood: "Uplifting", audio: "invincible.mp3", …}
2: {_id: "5edd0cdc38cb55332ccbd8f4", name: "Sun Kiss", genre: "Electronic/Pop", mood: "Energetic", audio: "sun_kiss.mp3", …}
3: {_id: "5edd0cdc38cb55332ccbd8f5", name: "Wormhole", genre: "Electronic/Pop", mood: "Energetic", audio: "wormhole.mp3", …}
4: {_id: "5edd0cdc38cb55332ccbd8f3", name: "Pier Light", genre: "Country", mood: "Uplifting", audio: "pier_light.mp3", …}
length: 5
__proto__: Array(0)


Solution

  • react state is immutable, you can't mutate mood_list and genre_list directly, you should do this like so:

    useEffect(() => {
      const fetchData = async () => {
        let { data = { songs = [] } = {} } = await axios.get('/api/songs')
        setItems(songs);
        setMood([...new Set(songs.map(x => x.mood))]);
        setGenre([...new Set(songs.map(x => x.genre))]);
      }
      fetchData();
    }, []);