ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2019-11-08 15:38:29  阅读:247  来源: 互联网

标签:reactjs redux javascript


我正在尝试开发一个应用程序,该应用程序显示给定关键字的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道具.

Example API response

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

当我阅读this post时,我认为这将是一个好主意,但是,我不确定如何由动作创建者处理此请求.

有什么办法可以用onclick处理程序调用排序功能?

解决方法:

您可以采用的一种方法是使用Redux reduxjs/reselect之类的库根据状态来计算派生数据,在这种情况下,根据某些对象键和/或方向对项目进行排序.选择器是可组合的,通常很有效,因为除非对其参数之一进行更改,否则它们不会重新计算.这种方法是在归约器的状态中为排序键和排序顺序添加属性.由于这些是通过操作/归约器在商店中更新的,因此选择器使用状态以结果排序的顺序派生元素.您可以在任何连接的组件中使用排序的项目.

我已经尽力重新创建了一个完整的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-更新了初始状态,以跟踪照片对象中存储的照片对象(例如项)的排序键和/或排序方向:

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,演示了实际的功能.它包括受控组件,例如和触发排序操作的分派.

希望有帮助!

标签:reactjs,redux,javascript
来源: https://codeday.me/bug/20191108/2009063.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有