如何移除React音乐库筛选下拉菜单中的重复选项
解决React音乐库筛选下拉菜单重复项问题
当前第二个筛选下拉菜单直接遍历所有歌曲生成选项,导致同一类别下的重复值多次出现。可以通过以下方案去除重复项:
实现思路
利用Set数据结构自动去重的特性,提取指定筛选类别下的唯一值,再转换为数组渲染选项。同时用useMemo缓存计算结果,避免不必要的重复计算,提升组件性能。
修改后的完整代码
import React, { useState, useEffect, useMemo } 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, artist, album, 'release_date': date, genre} await axios.post('http://127.0.0.1:8000/api/music/', songObject) // 新增歌曲后刷新列表,保证数据同步 getAllSongs() } 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)) } // 缓存去重后的选项数组,仅当songs或category变化时重新计算 const uniqueOptions = useMemo(() => { if (!category) return []; return [...new Set(songs.map(song => song[category]))]; }, [songs, category]); const displaySongs = (songsArr) => { return songsArr.map((song) =>( <tr key={song.id || `${song.title}-${song.release_date}`}> <td>{song?.title}</td> <td>{song?.artist}</td> <td>{song?.album}</td> <td>{song?.genre}</td> <td>{song?.release_date}</td> </tr> )) } return ( <div> <h1>Music Library</h1> <label htmlFor='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> {/* 使用去重后的数组渲染选项 */} {uniqueOptions.map(value => ( <option key={value} value={value}>{value}</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' value={title} onChange={handleTitleChange}/> <label> Artist </label> <input type='text' value={artist} onChange={handleArtistChange}/> <label> Album </label> <input type='text' value={album} onChange={handleAlbumChange}/> <label> Genre </label> <input type='text' value={genre} onChange={handleGenreChange}/> <label> Release Date </label> <input type='date' value={date} onChange={handleDateChange}/> <button onClick={postSong}>Add New Song</button> </form> </div> ); } export default App;
关键修改说明
- 去重逻辑:通过
new Set(songs.map(song => song[category]))提取指定类别的所有值并自动去重,再用扩展运算符[...]将Set转换为可遍历的数组。 - 性能优化:使用
useMemo缓存去重后的选项数组,仅当songs或category变化时重新计算,避免每次渲染重复执行去重操作。 - React key修复:为
<tr>和<option>添加唯一key,消除React控制台的列表项警告。 - 数据同步:新增歌曲后调用
getAllSongs()刷新列表,确保新增内容能立即在筛选选项中显示。
内容的提问来源于stack exchange,提问作者JonJon610
相关产品推荐
相关产品推荐

