React Hooks 如何按电影流派分组数据并渲染对应海报
按流派分组渲染电影海报的实现方案
核心问题根源:当前代码仅提取了去重的流派列表,没有建立「流派名称 -> 对应电影集合」的映射关系,因此渲染时无法找到每个流派下对应的海报资源。
实现思路
整个分组逻辑完全可以基于已获取的movies数据做衍生计算,不需要额外维护冗余状态,具体流程:
- 遍历所有电影数据,收集所有出现过的流派名称做去重,形成全量流派列表
- 为每一个流派筛选匹配的电影:只要某部电影的
genres数组包含该流派名称,就将这部电影归入对应流派的列表——完全满足「多流派电影需要同时出现在所属所有分组下」的规则 - 遍历每个流派分组,依次渲染流派标题、对应分组下的所有电影海报
优化后的完整实现代码
import React, { useState, useEffect, useMemo } from 'react'; function Genre() { const [movies, setMovies] = useState([]); const getMovies = async () => { try { const response = await fetch('你的请求地址', { headers: { Authorization: 'Bearer *********', }, }); const parseRes = await response.json(); setMovies(parseRes.movies || []); } catch (err) { console.error(err); } }; useEffect(() => { getMovies(); }, []); // 用useMemo缓存分组结果,仅在movies变化时重新计算,避免重复计算和多余状态更新 const genreGroupMap = useMemo(() => { const groupMap = {}; // 一次遍历完成全部分组映射构建 movies.forEach(movie => { movie.genres.forEach(genreName => { // 初始化未创建的流派分组 if (!groupMap[genreName]) { groupMap[genreName] = []; } // 将当前电影加入对应流派的列表 groupMap[genreName].push(movie); }) }) return groupMap; }, [movies]); const renderGenreGroups = () => { // 遍历所有流派分组做渲染 return Object.keys(genreGroupMap).map(genreName => { const groupMovies = genreGroupMap[genreName]; return ( <div key={genreName} style={{marginBottom: '24px'}}> <h3>Genre {genreName}</h3> <div style={{display: 'flex', gap: '12px', flexWrap: 'wrap'}}> {groupMovies.map((movie, idx) => ( <img key={idx} src={movie.picture} alt={`${genreName}类型电影海报`} style={{width: '120px', height: '180px', objectFit: 'cover'}} /> ))} </div> </div> ) }) }; return <React.Fragment>{renderGenreGroups()}</React.Fragment>; }
关键调整说明
- 移除了原来单独维护的
genre状态和对应的getGenre、useEffect更新逻辑:因为流派列表本身是从movies数据衍生的,用useMemo直接计算映射关系,既减少了多次状态更新带来的额外重渲染,也避免了两个状态不同步的问题 - 构建映射时直接遍历电影的genres数组做归并,比原来先收集流派、再二次筛选电影的写法性能更好,一次遍历就能完成分组
- 渲染海报时用flex布局实现海报横排自动换行,匹配预期的展示效果
- 列表渲染的key值使用稳定的流派名称、数组索引做标识,避免React列表渲染的告警
内容的提问来源于stack exchange,提问作者Henry
相关产品推荐
相关产品推荐

