gpt4 book ai didi

javascript - Redux:API 数据响应按点击排序

转载 作者:行者123 更新时间:2023-11-29 10:28:37 25 4
gpt4 key购买 nike

我正在尝试开发一个应用程序,该应用程序在给定关键字的情况下显示来自 Unsplash 的照片。我设法使用 unsplash.js 获取了特定的照片:

Action :

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);

和 reducer :

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 接收到的数据数组进行实际排序。响应是一个对象数组,因此无法在我称为 Buttons 的外部组件中调用它,我想在其中设置逻辑:

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 Prop 。

Example API response

我想对它们进行排序,例如,将 created_at 考虑在内。这将通过单击按钮来处理(还有其他按钮,比如喜欢的数量等等)。我尝试在 mapStateToProps 中执行此操作,直到我意识到无法使用 onClick 处理程序调用它。

正如我所读this post ,我认为这是一个好主意,但是,我不确定,我该如何处理 Action 创建者的这个请求。

有什么方法可以使用 onclick 处理程序调用排序函数?

最佳答案

您可以采用的一种方法是使用库,例如​​ Redux 的 reduxjs/reselect根据状态计算派生数据,在这种情况下,根据某些对象键和/或方向对项目进行排序。选择器是可组合的,并且通常是高效的,因为除非其中一个参数发生变化,否则不会重新计算它们。这种方法是将属性添加到 reducer 的状态以用于排序键和排序顺序。由于这些是通过 Action /缩减器在商店中更新的,因此选择器使用状态来导出结果排序顺序中的元素。您可以在任何连接的组件中使用排序的项目。

我已尽力重建一个完整的 example包括 Action 、缩减器、选择器和存储结构。

Actions - 创建用于设置排序键/方向的操作。我的示例使用 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 ,演示了实际的功能。它包括受控组件,例如并触发排序操作的分派(dispatch)。

希望对您有所帮助!

关于javascript - Redux:API 数据响应按点击排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52120500/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com