- 首页
- 其他开发
- 如何在redux中过滤和排序相同的对象状态数组?
如何在redux中过滤和排序相同的对象状态数组?
[英] How to filter and sort the same array of object state in redux?
本文介绍了如何在redux中过滤和排序相同的对象状态数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在开发电影收藏应用程序,其中有一个包含电影列表的页面.我想添加根据年份、流派和评级过滤电影的功能,并且我想按字母顺序、年份和评级对其进行排序.我如何通过使用 redux 来实现这一点,并通过使用单个状态对象做出反应.
解决方案
首先,我们应该创建一个组件来显示电影列表.
注意,这是一个纯粹的无状态组件,我们不会在那里进行排序或过滤,只是渲染派生的道具:
//Movies.js从反应"导入反应;功能电影({电影}){返回 (<ul>{movies.map((m, i) =><li key={i}>{m.year} - {m.title}.({m.genre}) - {m.rating}</li>)});}导出默认电影;
接下来我们将创建另一个无状态组件,其中将包含排序和过滤视图.
这里我们还渲染道具,并为 select
元素提供回调:
//Pane.js从反应"导入反应;功能窗格({选择年份,选择的流派,选择评级,年 = [],流派 = [],评分 = [],排序,onYearChange,关于流派变化,onRatingChange,onSortingChange,}) {返回 (<div><div>过滤器:<div>年:<选择默认值={selectedYear}onChange={e =>onYearChange(e.target.value)}><option value="all" >All</option>{years.map((y, i) =><option key={i} value={y}>{y}</option>)}</选择>
<div>类型:<选择defaultValue={selectedGenre}onChange={e =>onGenreChange(e.target.value)}><option value="all" >All</option>{genres.map((g, i) =><option key={i} value={g}>{g}</option>)}</选择>
<div>评分:<选择默认值={selectedRating}onChange={e =>onRatingChange(e.target.value)}><option value="all" >All</option>{ratings.map((r, i) =><option key={i} value={r}>{r}</option>)}</选择>
<div>选择排序:<选择默认值={排序}onChange={e =>onSortingChange(e.target.value)}><option value="alphabetically">Alphabetically</option><option value="year">Year</option><option value="rating">Rating</option></选择>
);}导出默认窗格;
我们将在应用状态中存储电影和所有过滤和排序数据.我们需要创建reducer,来处理排序和过滤操作:
//reducers.js常量项 = [{title: '疯狂的麦克斯',年份: 2015,评分:8,类型:'幻想',}, {title: '蜘蛛侠 2',年份: 2014,评分:7,类型:'幻想',}, {title: '钢铁侠3',年份: 2013,评分:7,类型:'幻想',}, {title: 'Dumb and Dumber To',年份: 2014,评分:5,类型:喜剧",}, {标题:'泰德 2',年份: 2015,评分:6,类型:喜剧",}];导出默认函数moviesReducer(state = {电影:物品,年份:'全部',评分:全部",类型:'所有',排序:'年',}, 行动) {开关(动作.类型){案例SET_YEAR":返回 {...状态,年:行动年,};案例SET_RATING":返回 {...状态,评级:action.rating,};案例SET_GENRE":返回 {...状态,流派:动作.流派,};案例SET_SORTING":返回 {...状态,排序:action.sorting,};默认:返回状态;}}
为了给无状态组件提供数据,我们应该使用containers
.
让我们创建PaneContainer
来为Pane
提供排序和过滤数据> 组件:
//PaneContainer.js从'react-redux'导入{连接};从'./Pane'导入窗格;//简单的辅助函数,它通过给定的键从状态返回所有过滤器.功能getFilters(键,电影){返回movies.reduce((acc,movie) => {如果(!acc.includes(电影[key])){返回 [...acc, 电影 [key]];}返回acc;}, []);}函数 mapStateToProps(state, props) {const { 排序,年份,流派,评级 } = 状态;返回 {选择年份:年份,selectedGenre:流派,selectedRating:评级,年:getFilters('year', state.movies),流派:getFilters('genre', state.movies),评分:getFilters('rating', state.movies),排序,};}函数 mapDispatchToProps(dispatch, props) {返回 {//在这里,我们提供带有调度函数的回调.onYearChange(年){派遣({类型:'SET_YEAR',年,});},onGenreChange(流派){派遣({类型:'SET_GENRE',类型,});},onRatingChange(评级){派遣({类型:'SET_RATING',评分,});},onSortingChange(排序){派遣({类型:'SET_SORTING',排序,});},};}导出默认连接(mapStateToProps,mapDispatchToProps)(窗格);
最后,我们将创建 MoviesContainer
,它将为 Movies
组件提供可见的电影:
//MoviesContainer.js从'react-redux'导入{连接};从'./Movies'导入电影;//从状态中获取可见的电影.功能 getVisibleMovies(年份,流派,评级,排序,电影){回归电影.filter(m => {返回 ((year == 'all' || year == m.year) &&(流派 == '所有' || 流派 == m.genre) &&(评级 == '所有' || 评级 == m.rating));}).sort((a, b) => {如果(排序=='年份'){返回 b.year - a.year;}如果(排序=='评级'){返回 b.rating - a.rating;}如果(排序 == '按字母顺序'){返回 a.title >b.标题?1 : a.title <b.标题?-1:0;}});}函数 mapStateToProps(state) {const { 年,流派,评级,排序,电影 } = 状态;返回 {电影:getVisibleMovies(年份,流派,评级,排序,电影),};}导出默认连接(mapStateToProps)(电影);
I am working on movie collection app , where i have a page with movie list. I want to add the functionality of filtering the movie based on year, genre and rating and also i want to sort it alphabetically ,year and rating. How can i accomplish that by using redux and react by using single state object.
解决方案
First, we should create component to display movies list.
Note, this is a pure stateless component, we are not making sorting or filtering there, just rendering derived props:
// Movies.js
import React from 'react';
function Movies({ movies }) {
return (
<ul>
{movies.map((m, i) =>
<li key={i}>{m.year} - {m.title}.({m.genre}) - {m.rating}</li>
)}
</ul>
);
}
export default Movies;
Next we will create another stateless component, which will contain sorting and filters view.
Here we are also rendering props, and providing callback to select
elements:
// Pane.js
import React from 'react';
function Pane({
selectedYear,
selectedGenre,
selectedRating,
years = [],
genres = [],
ratings = [],
sorting,
onYearChange,
onGenreChange,
onRatingChange,
onSortingChange,
}) {
return (
<div>
<div>
Filters:
<div>
Year:
<select
defaultValue={selectedYear}
onChange={e => onYearChange(e.target.value)}
>
<option value="all" >All</option>
{years.map((y, i) =>
<option key={i} value={y}>{y}</option>
)}
</select>
</div>
<div>
Genre:
<select
defaultValue={selectedGenre}
onChange={e => onGenreChange(e.target.value)}
>
<option value="all" >All</option>
{genres.map((g, i) =>
<option key={i} value={g}>{g}</option>
)}
</select>
</div>
<div>
Rating:
<select
defaultValue={selectedRating}
onChange={e => onRatingChange(e.target.value)}
>
<option value="all" >All</option>
{ratings.map((r, i) =>
<option key={i} value={r}>{r}</option>
)}
</select>
</div>
</div>
<div>
Select sorting:
<select
defaultValue={sorting}
onChange={e => onSortingChange(e.target.value)}
>
<option value="alphabetically">Alphabetically</option>
<option value="year">Year</option>
<option value="rating">Rating</option>
</select>
</div>
</div>
);
}
export default Pane;
We will store movies and all filtering and sorting data in app state.
We need create reducer, to handle sorting and filtering actions:
// reducers.js
const items = [{
title: 'Mad max',
year: 2015,
rating: 8,
genre: 'fantasy',
}, {
title: 'Spider man 2',
year: 2014,
rating: 7,
genre: 'fantasy',
}, {
title: 'Iron man 3',
year: 2013,
rating: 7,
genre: 'fantasy',
}, {
title: 'Dumb and Dumber To',
year: 2014,
rating: 5,
genre: 'comedy',
}, {
title: 'Ted 2',
year: 2015,
rating: 6,
genre: 'comedy',
}];
export default function moviesReducer(state = {
movies: items,
year: 'all',
rating: 'all',
genre: 'all',
sorting: 'year',
}, action) {
switch (action.type) {
case 'SET_YEAR':
return {
...state,
year: action.year,
};
case 'SET_RATING':
return {
...state,
rating: action.rating,
};
case 'SET_GENRE':
return {
...state,
genre: action.genre,
};
case 'SET_SORTING':
return {
...state,
sorting: action.sorting,
};
default:
return state;
}
}
To provide data to stateless components, we should use containers
.
Let's create PaneContainer
to provide sorting and filtering data to Pane
component:
// PaneContainer.js
import { connect } from 'react-redux';
import Pane from './Pane';
// Simple helper function, which return all filters from state by given key.
function getFilters(key, movies) {
return movies.reduce((acc, movie) => {
if (!acc.includes(movie[key])) {
return [...acc, movie[key]];
}
return acc;
}, []);
}
function mapStateToProps(state, props) {
const { sorting, year, genre, rating } = state;
return {
selectedYear: year,
selectedGenre: genre,
selectedRating: rating,
years: getFilters('year', state.movies),
genres: getFilters('genre', state.movies),
ratings: getFilters('rating', state.movies),
sorting,
};
}
function mapDispatchToProps(dispatch, props) {
return {
// Here, we are providing callbacks with dispatching functions.
onYearChange(year) {
dispatch({
type: 'SET_YEAR',
year,
});
},
onGenreChange(genre) {
dispatch({
type: 'SET_GENRE',
genre,
});
},
onRatingChange(rating) {
dispatch({
type: 'SET_RATING',
rating,
});
},
onSortingChange(sorting) {
dispatch({
type: 'SET_SORTING',
sorting,
});
},
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Pane);
And finally, we will create MoviesContainer
which will provide visible movies to Movies
component:
// MoviesContainer.js
import { connect } from 'react-redux';
import Movies from './Movies';
// Getting visible movies from state.
function getVisibleMovies(year, genre, rating, sorting, movies) {
return movies
.filter(m => {
return (
(year == 'all' || year == m.year) &&
(genre == 'all' || genre == m.genre) &&
(rating == 'all' || rating == m.rating)
);
})
.sort((a, b) => {
if (sorting == 'year') {
return b.year - a.year;
}
if (sorting == 'rating') {
return b.rating - a.rating;
}
if (sorting == 'alphabetically') {
return a.title > b.title ? 1 : a.title < b.title ? -1 : 0;
}
});
}
function mapStateToProps(state) {
const { year, genre, rating, sorting, movies } = state;
return {
movies: getVisibleMovies(year, genre, rating, sorting, movies),
};
}
export default connect(mapStateToProps)(Movies);
这篇关于如何在redux中过滤和排序相同的对象状态数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文