首页 > 解决方案 > 减速器不能改变返回结果

问题描述

我有 3 个标签,如下所示:ALL|Top100|Spam

在第一次加载页面时,调用 ALL 并收到 257 条返回记录,然后单击“垃圾邮件”选项卡并收到 11 条返回记录。一切正常。

但是当我的当前页面是“垃圾邮件”时,我点击选项卡“全部”,我也收到了 11 条返回记录。错了!结果必须是 257 条记录。

经过调试,我发现这种情况下的“componentWillReceiveProps”只调用了一次,而在第一次加载页面时它调用了2次。导致Reducer 上的状态没有更新。

请帮我。

谢谢你们

这是我的代码:

  1. 邮递页

/**
 * Created by admin on 7/7/17.
 */
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import * as combineActions from '../../actions/index';
import { bindActionCreators } from 'redux';
import PostFilter from './PostFilter';
import PaginationView from '../common/PaginationView';
import { MODAL_TYPES } from '../../const';
import List from '../common/List';
import { I18n } from 'react-redux-i18n';
import toastr from 'toastr';
import moment from 'moment';
// import { showModal } from '../../actions/modalAction';
import PostForm from './PostForm';
const Translate = require('react-redux-i18n').Translate;

class PostPage extends Component {
	constructor(props, context) {
    super(props, context);
    this.state = {
      currentPage: props.paging.currentPage,
      displayMode: props.displayMode,
      searchKey: '',
      fromDate: '',
      toDate: '',
      flgRng: '',
      category: '',
    };
  }
  
  handleChangeDate =  (dateName, dateValue) => {
    let fromDate, toDate;
    if (dateName === 'fromDate') {
        fromDate = dateValue;
        this.setState({
          fromDate,
        })
    }else{
        toDate = dateValue;
        this.setState({
          toDate,
        })
    }
  }

  handlelChangeFilter = (event) => {
    this.setState({
        [event.target.name]: event.target.value
    });
  }

  handleSearch = () => {
    const { searchKey, category } = this.state;
    let { flgRng, fromDate, toDate } = this.state;

    const params = {};
    

    if(this.validate(fromDate, toDate) ===false) 
    {
      return;
    }

    if (category) {
        params['category.id'] = category;
    }
    let fD, tD;
    if(fromDate){
      fD = this.formatDate(fromDate);
      flgRng =  "1";
    }else{
      flgRng =  "";
    }

    if(toDate){
      tD = this.formatDate(toDate);
    }

    this.setState({
      flgRng
    })
    this.props.actions.fetchPosts({ SearchKey: searchKey, FromDate: fD, ToDate: tD, FlgRng: flgRng, Query: JSON.stringify(params), Mode: this.props.displayMode})
  }

  handleShowFormNew = () => {
    this.props.actions.showModal(
      MODAL_TYPES.POST_NEW,
      Object.assign(
        {
          title: I18n.t('common.delete_confirm'),
          message: <PostForm />,
          type: 'delete_confirm',
          handleOK: () => {},
        },
        this.props,
      ),
    );
  }

  validate = (fromDate, toDate) => {
    if(!fromDate && toDate){
      toastr.error(I18n.t('post.msg_fdate'));
      return false;
    }

    if(fromDate && (fromDate === null || fromDate === "" || Date.parse(fromDate) === NaN)){
      toastr.error(I18n.t('post.msg_format_fdate'));
      return false;
    }

    if(toDate && (toDate === null || toDate === "" || Date.parse(toDate) === NaN)){
      toastr.error(I18n.t('post.msg_format_tdate'));
      return false;
    }

    if(fromDate && toDate){
      fromDate = new Date(fromDate)
      toDate = new Date(toDate)
      if(fromDate > toDate){
        toastr.error(I18n.t('post.msg_compare_fdtd'));
        return false;
      }
    }
  }

  formatDate = (date) => {
    var d = new Date(date),
        month = '' + (d.getMonth() + 1),
        day = '' + d.getDate(),
        year = d.getFullYear();

    if (month.length < 2) month = '0' + month;
    if (day.length < 2) day = '0' + day;

    return [month, day, year].join('-');
  }

	componentWillMount() {
    this.props.actions.setCurrentPage(1);
    this.props.actions.fetchPosts();
    this.props.actions.fetchCategories();
  }

  deletePost = (item) => {
    this.props.actions.showModal(MODAL_TYPES.CONFIRM_MODAL, Object.assign({
			title: I18n.t('common.delete_confirm'),
      message: (<Translate value="members.delete_confirm_msg" name={item.content} dangerousHTML />),
			type: 'delete_confirm',
			handleOK: () => {
        this.props.actions.deletePost(item._id)
          .then(rs => {
            this.props.actions.hideModal();
            this.props.actions.triggerRefresh();
            toastr.success(I18n.t('post.post_deleted_success'));
          }).catch(error => {
            this.props.actions.hideModal();
            toastr.error(error.message || error);
          });
      }
		}, this.props));
  }
  
  componentWillReceiveProps(nextProps) {
    const triggerRefresh = this.props.triggerRefresh;
    let params = {};
    if((this.state.displayMode !== nextProps.displayMode)||(this.state.currentPage !== nextProps.paging.currentPage || triggerRefresh !== nextProps.triggerRefresh)){
        this.setState({ currentPage: nextProps.paging.currentPage, displayMode: nextProps.displayMode, searchKey: this.state.searchKey, fromDate: this.state.fromDate, toDate: this.state.toDate, flgRng: this.state.flgRng, category: this.state.category});
        if(this.state.category){
          params['category.id'] = this.state.category;
        }
        let fromDate, toDate, flgRng;
        if(this.validate(this.state.fromDate, this.state.toDate) ===false) 
        {
          return;
        }
        if(this.state.fromDate){
          fromDate = this.state.fromDate.format("MM-DD-YYYY");
          flgRng = "1"
        }
        if(this.state.toDate){
          toDate = this.state.toDate.format("MM-DD-YYYY");
        }
        this.props.actions.fetchPosts({PageNumber: nextProps.paging.currentPage , SearchKey: this.state.searchKey, FromDate: fromDate, ToDate: toDate, FlgRng: flgRng, Query: JSON.stringify(params), Mode: nextProps.displayMode})
      }
  }

  render() {
    const {posts, actions, triggerRefresh, categories, displayMode} = this.props;
    const {currentPage} = this.state;
    let data = []
    let listOptions = {}
    if(posts.items.length > 0 && posts.items[0].spamRecs && displayMode ==='spam'){
      data = posts.items.length > 0 ? posts.items.map(key => {
        key.name = key.author? `${key.author.firstName} ${key.author.lastName}`: '';
        key.categoryName = key.category ? key.category.name : '';
        key.createdDate = moment(key._created).format('MM/DD/YYYY');
        key.reportedDate = key.spamRecs ? moment(key.spamRecs['_created']).format('MM/DD/YYYY') : "";
        key.numberReport = key.spamRecs ? key.spamRecs.length : 0
        return key;
      }): []
      
      listOptions = {
          headers: [I18n.t('common.title'), I18n.t('post.category'), I18n.t('post.author'), I18n.t('post.created_date_time'), I18n.t('post.number_report'), I18n.t('post.reported_date'), I18n.t('common.action')],
          data: {
                  items: data,
                  mapping: ['content', 'categoryName','name', 'createdDate', 'numberReport', 'reportedDate',  'action'],
                  align:["","","","","center","",""],
                  render: [
                    {
                      key: "content",
                      render: (item) => {
                        return <div className="overflow" style={{ width: '180px'}}>{item.content}</div>
                      }
                    },
                    {
                      key: "categoryName",
                      render: (item) => {
                        return <div className="overflow" style={{ width: '140px'}}>{item.categoryName}</div>
                      }
                    },
                    {
                      key: "name",
                      render: (item) => {
                        return <div className="overflow" style={{ width: '60px'}}>{item.name}</div>
                      }
                    }
                  ],
              },
          params: {url: '/posts/detail/%s/info' + '/' +this.state.displayMode, deleteAction: this.deletePost},
          count: posts.count
      };
    }else{
      data = posts.items.length > 0 ? posts.items.map(key => {
      key.name = key.author? `${key.author.firstName} ${key.author.lastName}`: '';
      key.numberComment = key.comments ? key.comments.length: 0;
      key.numberLike = key.likes ? key.likes.length : 0;
      key.categoryName = key.category ? key.category.name : '';
      key.createdDate = moment(key._created).format('MM/DD/YYYY');
      return key;
      }): []
    
      listOptions = {
      headers: [I18n.t('common.title'), I18n.t('post.category'), I18n.t('post.author'), I18n.t('post.created_date_time'), I18n.t('post.number_comment'), I18n.t('post.number_view'), I18n.t('post.number_like'), I18n.t('common.action')],
      data: {
              items: data,
              mapping: ['content', 'categoryName','name', 'createdDate', 'numberComment', 'views', 'numberLike',  'action'],
              align:["","","","","center","center","center",""],
              render: [
                {
                  key: "content",
                  render: (item) => {
                    return <div className="overflow" style={{ width: '180px'}}>{item.content}</div>
                  }
                },
                {
                  key: "categoryName",
                  render: (item) => {
                    return <div className="overflow" style={{ width: '140px'}}>{item.categoryName}</div>
                  }
                },
                {
                  key: "name",
                  render: (item) => {
                    return <div className="overflow" style={{ width: '60px'}}>{item.name}</div>
                  }
                }
              ],
          },
      params: {url: '/posts/detail/%s/info' + '/' +this.state.displayMode, deleteAction: this.deletePost},
      count: posts.count
    };
  }
    return (
      <div className="table-page">
        <h4 className="module-title">{I18n.t('post.page.title')}</h4>
        <PostFilter 
          categories={categories}
          searchKey={this.state.searchKey} 
          fromDate={this.state.fromDate} 
          toDate={this.state.toDate}
          onSearch={this.handleSearch}
          onShow={this.handleShowFormNew}
          onChangeDate = {this.handleChangeDate}
          onChangeFilter = {this.handlelChangeFilter}
        /> 
        
        <List {...listOptions} />
        <PaginationView count={posts.count} currentPage={currentPage} onSelectPage={(page) => {actions.setCurrentPage(page)}}/>
      </div>
    );
  }
}

function mapStateToProps(state, ownProps) {
	return {
    posts: state.posts.page,
    categories: state.posts.categories,
    paging: state.paging,
    i18n: state.i18n,
    triggerRefresh: state.posts.triggerRefresh
	};
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(combineActions, dispatch)
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(PostPage);

  1. 帖子减速器

/**
 * Created by admin on 7/12/17.
 */
import {POSTS} from '../const/actionTypes';

const initialState = {
    page: {
        items: [],
        count: 0
    },
    detail: {},
    post: {
        items: [],
        count: 0
    },
    comment: {
        items: [],
        count: 0
    },
    triggerRefresh: false,
    categories: [],
    currentP: {},
    pListComment: [],
    pList: [],
    pListReporter: [],
};

export default function posts(state = initialState, action) {
    switch(action.type) {
        case POSTS.FETCH_SUCCESS:
            return {...state, page: {items: action.payload.items, count: action.payload.count}};
        case POSTS.FETCH_CATEGORY_SUCCESS:
            return {...state, categories: action.payload};
        case POSTS.TRIGGER_REFRESH: 
            return {...state, triggerRefresh: !state.triggerRefresh}
        case POSTS.GET_POST_DETAIL_SUCCESS:
            return { ...state, currentP: Object.assign({}, action.payload) };
        case POSTS.CREATE_SUCCESS:
            return { ...state, pList: [action.payload, ...state.pList], currentP: {} };
        case POSTS.UPDATE_SUCCESS:
            let updated = action.payload;
            let newItems = state.pList.map(p => {
                return p._id === updated._id ? Object.assign({}, p, updated) : p;
            });
            return { ...state, pList: newItems, currentPS: action.payload };
        case POSTS.DELETE_POSTS_SUCCESS:
            return { ...state, pList: state.pList.filter(item => item._id != action.payload) };
        case POSTS.GET_POST_COMMENT_SUCCESS:
            return { ...state, pListComment: action.payload };
        case POSTS.GET_POST_REPORTER_SUCCESS:
            return { ...state, pListReporter: action.payload };
        default:
            return state;
    }
}

标签: reactjs

解决方案


推荐阅读