reactjs 如何从过滤器下拉列表中删除重复项

km0tfn4u  于 2023-03-12  发布在  React
关注(0)|答案(2)|浏览(275)

我正在开发一个音乐库,希望用户能够通过选择歌曲进行过滤。我有一个后端API,其中创建了歌曲对象,包括标题、艺术家、专辑、流派发布日期。我能够创建2个下拉菜单,其中第一个下拉菜单允许用户选择他们想要过滤的类别,例如专辑。第二个下拉菜单应该允许用户根据所选的类别进行选择,但是我在那里有重复的。2我显然不想重复。

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function App() {

  const [songs, setSongs] = useState([])

  const [title, setTitle] = useState('')
  
  const [artist, setArtist] = useState('')

  const [album, setAlbum] = useState('')

  const [genre, setGenre] = useState('')
  
  const [date, setDate] = useState('')

  const [category, setCategory] = useState('')

  const [choice, setChoice] =useState([])

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

  async function getAllSongs() {
    const response = await axios.get('http://127.0.0.1:8000/api/music/');
    const allSongs = response.data
    setSongs(allSongs)
  }

  async function postSong(event){
    event.preventDefault()
    // const songObject = {'title': title, 'artist': artist, 'album': album, 'release_date': date, 'genre': genre}
    const songObject = {title, artist, album, 'release_date': date, genre}
    await axios.post('http://127.0.0.1:8000/api/music/', songObject)
  }

  const handleTitleChange = (event) => {
    setTitle(event.target.value)
  }

  const handleArtistChange = (event) => {
    setArtist(event.target.value)
  }

  const handleAlbumChange = (event) => {
    setAlbum(event.target.value)
  }

  const handleGenreChange = (event) => {
    setGenre(event.target.value)
  }

  const handleDateChange = (event) => {
    setDate(event.target.value)
  }

  const handleCategoryChange = (event) => {
    setCategory(event.target.value)
  }
  
  const handleChoiceChange = (event) => {
    setChoice(songs.filter((song) => song[category] === event.target.value))
  }

  const displaySongs = (songsArr) => {
    return songsArr.map((song) =>(
      <tr>
        <td>{song?.title}</td>
        <td>{song?.artist}</td>
        <td>{song?.album}</td>
        <td>{song?.genre}</td>
        <td>{song?.release_date}</td>
      </tr>
      ))
  }

  // As a developer, I want to display the data (song title, album, artist, genre, and release date) from the API within a table on the frontend. 

  return (
    <div>
        <h1>Music Library</h1>
        <label for='songs'>Filter: </label>
        <select name='categories' value={category} onChange={handleCategoryChange}>
          <option value="">Select your category</option>
          <option value='title'>Title</option>
          <option value='artist'>Artist</option>
          <option value='genre'>Genre</option>
          <option value='album'>Album</option>
          <option value='release_date'>Release Date</option>
        </select>
        <select name='choice' onChange={handleChoiceChange}>
          <option value="">Select the {category}</option>
          {songs.map((song) => (
           <option>{song[category]}</option>
          ))}
        </select>
        <table>
          <tr>
            <th>Title</th>
            <th>Artist</th>
            <th>Album</th>
            <th>Genre</th>
            <th>Release Date</th>
          </tr>
          {choice.length > 0 ? displaySongs(choice): displaySongs(songs)}
        </table>
        <form>
          <label>Title </label>
          <input type='text' onChange={(event) => handleTitleChange(event)}/>
          {/* <input type='text' onChange={function(event) {return handleTitleChange(event)}}/> */}
          <label> Artist </label>
          <input type='text' onChange={(event) => handleArtistChange(event)}/>
          <label> Album </label>
          <input type='text' onChange={(event) => handleAlbumChange(event)}/>
          <label> Genre </label>
          <input type='text' onChange={(event) => handleGenreChange(event)}/>
          <label> Release Date </label>
          <input type='date' onChange={(event) => handleDateChange(event)}/>
          {/* <input type='submit'value='Add New Song'/> */}
          <button onClick={(event) => postSong(event)} >Add New Song</button>
        </form>
    </div>
  );
}

export default App;
lstz6jyr

lstz6jyr1#

您需要从对象数组中“提取”唯一类别(歌曲),并将其作为选项列表提供给第二个下拉列表。在JavaScript中有多种方法可以实现这一点。最直接的方法是创建一个新数组const categories = []并使用songs.forEach()循环(read docs)来迭代songs。在回调类中,将数组推送到categories,检查它是否还不存在。此外,您还可以检查Array.reduce()read more)以获得可能的解决方案。但我会使用以下方法:

const songs = [
  { name: "Billy Jean", category: "pop" },
  { name: "Black and White", category: "pop" },
  { name: "Smells Like Teen Spirit", category: "rock" },
  { name: "I Love Rock'n'roll", category: "rock" },
  { name: "Enter Sandman", category: "metal" },
];

const categories = [...(new Set(songs.map(song => song.category)))];

console.log(categories);
cs7cruho

cs7cruho2#

过滤功能可用于检索与特定类别相关的歌曲。请尝试:

<select name='choice' onChange={handleChoiceChange}>
    <option value="">Select the {category}</option>
       {songs
          .filter(x => x.category === category)
          .map((song) => (
               <option value={song.name}>{song.name} -- {song.category} 
               </option>
        ))}
  </select>

如果你想在第二个下拉列表中设置一个默认值const [category,setCategory] = useState('title ')

相关问题