我正在尝试开发一个应用程序,即显示来自Unsplash的照片给出一个关键字。我设法使用unsplash.js获取特定照片:
动作:
export function fetchPhotos(term) {
const unsplash = new Unsplash({
applicationId:
"id",
secret: "secret",
callbackUrl: "callback"
});
const response = unsplash.search
.photos(term, 1, 20)
.then(toJson)
.then(json => json);
return {
type: FETCH_PHOTOS,
payload: response
};
}
export function setCategory(term) {
return {
type: SET_CATEGORY,
categories: [term]
};
}
export function sortPhotos(attribute) {
return {
type: SORT_PHOTOS,
attribute
}
}
渲染照片的组件:
import React, { Component } from "react";
import { connect } from "react-redux";
import SinglePhoto from "../components/SinglePhoto";
class PhotoList extends Component {
renderPhotos() {
const { photos } = this.props;
console.log(photos);
if (!photos) {
return <p>Loading...</p>;
}
return photos.map(photo => {
const url = photo.urls.full;
const id = photo.id;
const alt = photo.description;
return <SinglePhoto url={url} key={id} alt={alt} />;
});
}
render() {
return <div>{this.renderPhotos()}</div>;
}
}
function mapStateToProps(state) {
return {
photos: state.photos,
categories: state.categories
};
}
export default connect(mapStateToProps)(PhotoList);
减速机:
import { FETCH_PHOTOS, SORT_PHOTOS } from "../actions/types";
export default function(state = [], action) {
switch (action.type) {
case FETCH_PHOTOS:
return [...action.payload.results];
case SORT_PHOTOS:
break;
default:
return state;
}
}
我正在努力做的是实际排序我根据特定术语从API接收的数据数组。响应是一个对象数组,这使得无法在外部组件中调用它我称之为按钮,我想在其中设置逻辑:
class Buttons extends Component {
render() {
const { created_at: date } = this.props.photos;
console.log(this.props);
return (
<div className="buttons">
{/* <button onClick={() => this.props.sortPhotos(date)}>Sort by creation date</button> */}
</div>
)
}
}
const mapStateToProps = (state) => {
return {
photos: state.photos
}
}
const mapDispatchToProps = (dispatch) => bindActionCreators({sortPhotos}, dispatch);
export default connect(mapStateToProps, mapDispatchToProps)(Buttons);
因为我需要循环遍历照片以实际接收他们的created_at道具。
我想对它们进行排序,例如,将created_at考虑在内。这可以通过按钮点击来处理(还有其他按钮可以说喜欢金额等等)。我试图在mapStateToProps中这样做,直到我意识到用onClick处理程序调用它是不可能的。
正如我读过this post,我认为这是一个好主意,但是,我不确定,我怎么能处理动作创建者的请求。
有没有办法用onclick处理程序调用排序函数?
您可以采用的一种方法是使用Redux的reduxjs/reselect等库来计算基于状态的派生数据,在这种情况下,基于某些对象键和/或方向对项目进行排序。选择器是可组合的,并且通常是高效的,因为它们不会被重新计算,除非它的一个参数发生变化。此方法是为reducer的状态添加属性以用于排序键和排序顺序。当这些通过actions / reducers在商店中更新时,选择器使用state来导出生成的排序顺序中的元素。您可以在任何连接的组件中使用已排序的项目。
我已经尽力重新创建一个完整的example,包括动作,缩减器,选择器和商店结构。
操作 - 创建用于设置排序键/方向的操作。我的例子是使用redux-thunk
来处理异步操作,但这绝不是必要的:
export const SET_SORT = 'SET_SORT';
const setSort = (sortDirection, sortKey) => ({
type: SET_SORT,
sortDirection,
sortKey
});
export const sort = (sortDirection = 'desc', sortKey = 'created_at') => dispatch => {
dispatch(setSort(sortDirection, sortKey));
return Promise.resolve();
};
Reducer - 更新初始状态以跟踪排序键和/或排序方向,其中照片对象存储在子属性(如items
)中:
const initialState = {
isFetching: false,
sortDirection: null,
sortKey: null,
items: []
};
const photos = (state = initialState, action) => {
switch (action.type) {
case FETCH_PHOTOS:
return {
...state,
isFetching: true
};
case RECEIVE_PHOTOS:
return {
...state,
isFetching: false,
items: action.photos
};
case SET_SORT:
return {
...state,
sortKey: action.sortKey,
sortDirection: action.sortDirection
};
default:
return state;
}
};
选择器 - 使用重新选择,创建用于检索项目/照片,sortOrder和sortDirection的选择器。显然可以增强排序逻辑来处理其他键/条件/等:
import { createSelector } from 'reselect';
const getPhotosSelector = state => state.photos.items;
const getSortKeySelector = state => state.photos.sortKey;
const getSortDirectionSelector = state => state.photos.sortDirection;
export const getSortedPhotosSelector = createSelector(
getPhotosSelector,
getSortKeySelector,
getSortDirectionSelector,
(photos, sortKey, sortDirection) => {
if (sortKey === 'created_at' && sortDirection === 'asc') {
return photos.slice().sort((a, b) => new Date(a.created_at) - new Date(b.created_at));
} else if (sortKey === 'created_at' && sortDirection === 'desc') {
return photos.slice().sort((a, b) => new Date(b.created_at) - new Date(a.created_at));
} else {
return photos;
}
}
);
组件 - 使用选择器来渲染项目。通过按钮单击传递排序键和/或排序顺序来触发排序操作的调度。链接的示例使用下拉列表与按钮单击组合以设置排序键/顺序:
import { getSortedPhotosSelector } from './selectors';
// ...
handleClick() {
this.props.dispatch(sort('desc', 'created_at'));
}
render() {
const { sortDirection, sortKey, items } = this.props;
<ul>
{items.map(item => <li key={item.id}>{item.created_at}</li>)}
</ul>
<button type="button" onClick={this.handleClick}>SORT</button>
}
const mapStateToProps = state => ({
items: getSortedPhotosSelector(state),
sortKey: state.photos.sortKey,
sortDirection: state.photos.sortDirection
});
export default connect(mapStateToProps)(PhotoList);
这是一个StackBlitz,展示了行动中的功能。它包括受控组件,例如和触发分派操作的分派。
希望这有帮助!