Ich arbeite an Film Sammlung App, wo ich eine Seite mit Film Liste habe. Ich möchte die Funktionalität hinzufügen, um den Film nach Jahr, Genre und Bewertung zu filtern und ich möchte auch alphabetisch, Jahr und Bewertung sortieren. Wie kann ich das erreichen, indem ich Redux benutze und mit einem einzelnen Zustandsobjekt reagiere?Wie das gleiche Array von Objektstatus in redux filtern und sortieren?
Antwort
Zuerst sollten wir eine Komponente erstellen, um die Filmliste anzuzeigen.
Note, ist dies eine reine zustandslose Komponente, wir sich nicht machen Sortieren oder Filtern, nur abgeleitete Requisiten Rendering:
// 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;
nächst wir eine andere zustandslose Komponente schaffen, wobei die Ansicht des Sortieren und Filtern enthalten.
Hier sind wir machen Requisiten auch, und zu select
Elemente Rückruf Bereitstellung:
// 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;
Wir Filme gespeichert werden und alle Filter- und Sortierdaten in App-Status. Wir brauchen Minderer zu erstellen, Sortieren und Filtern Aktionen zu handhaben:
// 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;
}
}
Um Daten zu staatenlos Komponenten zu liefern, sollten wir containers
verwenden.
Lassen Sie uns PaneContainer
erstellen zu schaffen Sortieren und Filtern von Daten zu Pane
Komponente:
// 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);
Und schließlich werden wir MoviesContainer
schaffen, die sichtbare Filme Movies
Komponente zur Verfügung stellt:
// 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);
Wo ist der Filmbehälter? Sie haben die Movies-Komponente importiert und dann mit dem Redux-Store verbunden. Das sieht nicht nach einer guten Praktik aus. Funktioniert dieser Code überhaupt? –
@IsaacPak 'Filme' Komponente ist am Anfang der Antwort definiert. 'MoviesContainer' ist am Ende definiert. Die Verwendung von 'connect', um die Daten von einem Redux-Speicher zu einer Komponente bereitzustellen, ist ein üblicher Ansatz. – 1ven
Ok. Ich habe meine Container mit dem Laden verbunden. Aber jetzt, nachdem ich diese [docs] (http://redux.js.org/docs/basics/UsageWithReact.html) überprüft habe, macht Ihr Code jetzt mehr Sinn. Vielen Dank! –
* nicht genug Ruf hat Comment 'key = {i}' zu machen und in 'getVisibleMovies' zu sortieren führt dazu, dass die gesamte Liste und das Listenelement neu gerendert werden. – uschen