React电影卡片横向排列问题求助:Flex/Grid如何正确应用?
React中实现MovieCard横向并排显示的解决方案
问题概述
在React项目中尝试让MovieCard组件横向并排显示,但卡片始终呈纵向排列,尝试多种div属性无效,需要明确是否使用Flex/Grid布局及正确应用方法。以下是相关组件代码:
MoviesList组件
import React, { useState } from 'react' import { useSelector } from 'react-redux' import MovieCard from './MovieCard' const MoviesList = (props) => { const [search, setSearch] = useState('') const [filterBy, setFilterBy] = useState([]) const [orderBy, setOrderBy] = useState('') const movies = useSelector((state) => { console.log(state.movies) return state.movies }) const handleChange = (e) => { const inputValue = e.target.value setSearch(inputValue) const filteredValue = movies.filter((movie) => { return movie.Title.toLowerCase().includes(inputValue) }) setFilterBy(filteredValue) console.log(filteredValue) } const handleSelectChange = (e) => { setOrderBy(e.target.value) } const show = (movies) => { switch (orderBy) { case 'a-z': return [...movies.sort((a, b) => a.Title.localeCompare(b.Title))] case 'z-a': return [...movies.sort((a, b) => b.Title.localeCompare(a.Title))] case '1-100': return [...movies.sort((a, b) => a.imdbRating - b.imdbRating)] case '100-1': return [...movies.sort((a, b) => b.imdbRating - a.imdbRating)] default: return [...movies] } } return ( <div className='container'> <div className='d-flex mb-3 '> <h1 style={{ textAlign: 'center', border: 'solid lightgreen', backgroundColor: 'white' }} >My Movie List</h1> <form style={{ float: 'right', marginRight: '35px' }}> <input type="text" placeholder='search by name' value={search} onChange={handleChange} /> <select value={orderBy} onChange={handleSelectChange} > <option value="">orderBy</option> <option value="a-z">a-z</option> <option value="z-a">z-a</option> <option value="1-100">1-100</option> <option value="100-1">100-1</option> </select> </form> </div> <div className=" row pt-2 justify-content-around " style={{ textAlign: 'center', width: '100%' }}> { filterBy.length > 0 ? ( filterBy.map((movie) => { return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} /> }) ) : ( show(movies).map((movie) => { return <MovieCard key={movie.imdbID} {...movie} /> }) ) } </div> </div > ) } export default MoviesList
MovieCard组件
import React from 'react' import { useDispatch } from 'react-redux' import { removeMovie } from '../actions/moviesAction' const MovieCard = (props) => { console.log(props) const { Title, Poster, imdbRating, imdbID } = props const dispatch = useDispatch() return ( <div className="card mt-2 p-2 bd-highlight border shadow rounded" style={{ width: '16rem' }}> <img className="card-img-left pt-2" src={Poster} alt={Title} style={{ width: '200px', height: '200px' }} /> <div className="card-body"> <h4 className="card-title">Name : {Title}</h4> <h5 className="card-title">Ranking : #{imdbRating}</h5> <ion-icon name="trash" style={{ color: 'red' }} onClick={() => { dispatch(removeMovie(imdbID)) }}></ion-icon> </div> </div> )} export default MovieCard
解决方案
你可以通过Bootstrap栅格系统(你已在使用Bootstrap)、Flex布局或Grid布局实现横向排列,以下是具体实现方式:
方式1:利用Bootstrap栅格系统(最简便,适配现有代码)
你已经使用了Bootstrap的row类,只需给每个MovieCard外层添加Bootstrap的列类(如col-md-3),即可让卡片自动横向排列并响应式适配屏幕:
修改MoviesList组件中渲染MovieCard的部分:
{ filterBy.length > 0 ? ( filterBy.map((movie) => { return ( <div key={movie.imdbID} className="col-md-3 mb-4"> <MovieCard Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} /> </div> ) }) ) : ( show(movies).map((movie) => { return ( <div key={movie.imdbID} className="col-md-3 mb-4"> <MovieCard {...movie} /> </div> ) }) ) }
col-md-3表示在中等屏幕及以上,每行显示4个卡片(12/3=4);mb-4添加底部间距,避免卡片紧贴。
方式2:使用Flex布局
给包裹MovieCard的容器添加Flex样式,让卡片横向排列并自动换行:
修改MoviesList中包裹卡片的div:
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem', justifyContent: 'center', width: '100%', paddingTop: '1rem' }}> {/* 渲染MovieCard的代码 */} </div>
display: flex启用Flex布局;flexWrap: wrap让卡片在容器宽度不足时自动换行;gap: 1rem设置卡片之间的间距;justifyContent: 'center'让卡片居中排列。
方式3:使用Grid布局
通过Grid布局实现更灵活的卡片排列,自动根据容器宽度调整每行数量:
修改包裹卡片的div样式:
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(16rem, 1fr))', gap: '1rem', width: '100%', paddingTop: '1rem' }}> {/* 渲染MovieCard的代码 */} </div>
gridTemplateColumns: 'repeat(auto-fill, minmax(16rem, 1fr))'表示自动填充列,每列最小宽度为16rem(和你的卡片宽度一致),剩余空间平均分配;gap: 1rem设置卡片之间的间距。
以上三种方式都能解决卡片纵向排列的问题,推荐优先使用Bootstrap栅格系统,因为你已经在项目中引入了Bootstrap,风格更统一。
内容的提问来源于stack exchange,提问作者dharani
相关产品推荐
相关产品推荐

