我正在更新状态时,我的prevProps和componentDidUpdate中的当前道具相同

时间:2019-09-21 06:11:01

标签: reactjs

我在表中添加了排序工具。当我对一个元素进行排序或删除时,会有2个数组相同,其中一个是prevprops,另一个是当前props。我查看了我的代码,发现以下代码段出了错误。

这是我的Pagination.js代码

import React from "react"

const propTypes = {
    // items: React.PropTypes.array.isRequired,
    // onChangePage: React.PropTypes.func.isRequired,
    // initialPage: React.PropTypes.number    
}

const defaultProps = {
    initialPage: 1
}

class Pagination extends React.Component {
    constructor(props) {
        super(props);
        this.state = { pager: {} };
    }

    componentWillMount() {
        //set page if items array isn't empty
        if (this.props.items && this.props.items.length) {
            this.setPage(this.props.initialPage);
     }
  }

    // componentDidUpdate(prevProps,prevState) {

    //     if (this.props.items !== prevProps.items) {
    //         this.setPage(this.props.initialPage);     
    //     }



    // }
    componentWillReceiveProps (newProps) {
          if (this.props.items !== newProps.items) {
            this.setPage(this.props.initialPage);     
        }  
    }

    setPage(page) {

        var items = this.props.items;
        var pager = this.state.pager;
        if (page < 1 || page > pager.totalPages) {
            return;
        }
        // get new pager object for specified page
        pager = this.getPager(items.length, page);


        // get new page of items from items array
        var pageOfItems = items.slice(pager.startIndex, pager.endIndex + 1);

        // update state
        this.setState({ pager: pager });

        // call change page function in parent component

        this.props.onChangePage(pageOfItems);

    }

    getPager(totalItems, currentPage, pageSize) {
        // default to first page
        currentPage = currentPage || 1;

        // default page size is 10
        pageSize = pageSize || 10;

        // calculate total pages
        var totalPages = Math.ceil(totalItems / pageSize);

        var startPage, endPage;
        if (totalPages <= 10) {
            // less than 10 total pages so show all
            startPage = 1;
            endPage = totalPages;
        } else {
            // more than 10 total pages so calculate start and end pages
            if (currentPage <= 6) {
                startPage = 1;
                endPage = 10;
            } else if (currentPage + 4 >= totalPages) {
                startPage = totalPages - 9;
                endPage = totalPages;
            } else {
                startPage = currentPage - 5;
                endPage = currentPage + 4;
            }

        }

        // calculate start and end item indexes
        var startIndex = (currentPage - 1) * pageSize;
        var endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);

        // create an array of pages to ng-repeat in the pager control
        var pages = [...Array((endPage + 1) - startPage).keys()].map(i => startPage + i);

        // return object with all pager properties required by the view
        return {
            totalItems: totalItems,
            currentPage: currentPage,
            pageSize: pageSize,
            totalPages: totalPages,
            startPage: startPage,
            endPage: endPage,
            startIndex: startIndex,
            endIndex: endIndex,
            pages: pages
        };
    }

    render() { 

        var pager = this.state.pager;

        if (!pager.pages || pager.pages.length <= 1) {
            // don't display pager if there is only 1 page
            return null;
        }

        return (
            <ul className="pagination">
                <li className={pager.currentPage === 1 ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(1)}>First</a></li>
                <li className={pager.currentPage === 1 ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(pager.currentPage - 1)}>Previous</a>
                </li>
                {pager.pages.map((page, index) =>
                <li key={index} className={pager.currentPage === page ? 'active' : ''}>
                    <a onClick={() => this.setPage(page)}>{page}</a>
                </li>
                )}
                <li className={pager.currentPage === pager.totalPages ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(pager.currentPage + 1)}>Next</a>
                </li>
                <li className={pager.currentPage === pager.totalPages ? 'disabled' : ''}>
                    <a onClick={() => this.setPage(pager.totalPages)}>Last</a>
                </li>
            </ul>
        );
    }
}

Pagination.propTypes = propTypes;
Pagination.defaultProps = defaultProps;

export default Pagination

这是我的App.js代码

import React from 'react';
import "./App.css"
import Table from "./components/table"
import SearchBar from "./components/search"
import "antd/dist/antd.css";
import data from "./data"
import Pagination from "./components/pagination"

export default class App extends React.Component {
constructor(props){   
  super(props);
  // var exampleItems = [...Array(150).keys()].map(i => ({ id: (i+1), name: 'Item ' + (i+1) }))
  this.state={  
   filterText:"",
    // products:data,
    // currentPage: 1,
    // todosPerPage: 3,
    exampleItems:data,  
    pageOfItems: [],  
  }
  this.onChangePage = this.onChangePage.bind(this);
  this.handleRowDel = this.handleRowDel.bind(this)
}
// componentWillMount(){
//this.setState({exampleItems: this.state.products})
// }

onChangePage(pageOfItems) {
  // update state with new page of items
  this.setState({ pageOfItems: pageOfItems });

}

handleUserInput = (filterText) => {
  this.setState({filterText:filterText})  
}

handleProductTable = (evt) => {

  let item = {
    id: evt.target.id,
    name: evt.target.name,
    value: evt.target.value
  };

  let products = this.state.exampleItems;

  let newProducts = products.map(function(product) {

    Object.keys(product).forEach(key => {
      // eslint-disable-next-line
      if (key == item.name && product.id == item.id) {      
             product[key] = item.value;
           }
    })

    // for (var key in product) {
    //   // eslint-disable-next-line
    //   console.log(key);
    //   if (key == item.name && product.id == item.id) {      
    //     product[key] = item.value;
    //   }
    // }

    return product;
  });
  this.setState({exampleItems:newProducts});
};

async handleRowDel (product){
  const { exampleItems } = this.state;
  let index = exampleItems.indexOf(product);
  exampleItems.splice(index, 1);
 await this.setState({exampleItems:exampleItems}); 

};

handleAddEvent = (one,two,three,four) =>{
  let products= this.state.exampleItems;
  let count = + new Date();
  let item={
    id: count,
    name: one,
    price: two,
    qty: three,
    category: four,
  }
  products.push(item);
  this.setState({exampleItems:products}); 
}

orderChange = (e) =>{
  var  trimText = e.substr(4);
  var  arrangeMethod = e.substr(0,3);
  if(trimText === "price" || trimText === "qty") {
    this.arrangeNumber(trimText, arrangeMethod);
  }
  if(trimText === "category"){
    this.arrangeText(trimText,arrangeMethod);
  }

}

arrangeNumber = (key,arrangeMethod) =>{
  let arraycopy = this.state.exampleItems;
  if(arrangeMethod === "asc"){
    arraycopy.sort(function(a,b){
      if(Number(a[key]) < Number(b[key])){ return -1;}
      if(Number(a[key]) > Number(b[key])){ return 1;}
      return 0
    })
  }
  if(arrangeMethod === "des"){
    arraycopy.sort(function(a,b){
      if(Number(a[key]) > Number(b[key])){ return -1;}
      if(Number(a[key]) < Number(b[key])){ return 1;}
      return 0
    })
  }

 this.setState({exampleItems:arraycopy});

}
arrangeText = (key,arrangeMethod) =>{
  let arraycopy = this.state.exampleItems;
  if(arrangeMethod === "asc"){
    arraycopy.sort(function(a,b){
      if((a[key]) < (b[key])){ return -1;}
      if((a[key]) > (b[key])){ return 1;}
      return 0
    })
  }
  if(arrangeMethod === "des"){
    arraycopy.sort(function(a,b){
      if((a[key]) > (b[key])){ return -1;}
      if((a[key]) < (b[key])){ return 1;}
      return 0
    })
  }

 this.setState({exampleItems:arraycopy});
}

handleClick = (event) =>{
  this.setState({
    currentPage: Number(event.target.id)
  });
}

  render(){

    // const { currentPage, todosPerPage,products } = this.state;
    // // Logic for displaying current todos
    // const indexOfLastTodo = currentPage * todosPerPage;
    // const indexOfFirstTodo = indexOfLastTodo - todosPerPage;
    // console.log(products.slice(indexOfFirstTodo,indexOfLastTodo));
    // const currentTodos = products.slice(indexOfFirstTodo, indexOfLastTodo);
    // const renderTodos = currentTodos.map((todo, index) => {
    //   return <li key={index}>{todo}</li>;
    //    });  
    // const pageNumbers = [];
    //   for (let i = 1; i <= Math.ceil(products.length / todosPerPage); i++) {
    //     pageNumbers.push(i);
    //   }
    // const renderPageNumbers = pageNumbers.map(number => {
    //     return (
    //       <li
    //         key={number}
    //         id={number}
    //         onClick={this.handleClick}
    //       >
    //         {number}
    //       </li>
    //     );
    //   });
    return(
      <div>
        {/* <SearchBar 
          filterText={this.state.filterText} 
          onUserInput={this.handleUserInput} 
        />       */

        }
        <Table 
          onProductTableUpdate={this.handleProductTable} 
          onRowAdd={this.handleAddEvent} 
          products={this.state.pageOfItems}
          // currentTodos
          onDelEve={this.handleRowDel}
          filterText={this.state.filterText} 
          orderChange={this.orderChange}
        /><div className="pagination">  
          {/* <ul id="page">
           {renderPageNumbers}
          </ul> */}
      </div>

      <div className="container">
                    <div className="text-center">

                        {/* {this.state.pageOfItems.map(item =>
                            <div key={item.id}>{item.name}</div>
                        )} */ }

                        <Pagination items={this.state.exampleItems} onChangePage={this.onChangePage} />
                    </div>
                </div>



      </div>

    );
  }

}

您能告诉我我应该在哪里更改代码吗?

1 个答案:

答案 0 :(得分:0)

您有几个实例在其中改变状态。在反应中,您的状态为needs to be immutable,否则无法进行前后比较,因为前后是同一回事。例如,您在这里有以下代码:

handleAddEvent = (one,two,three,four) => {
  let products = this.state.exampleItems;
  let count = + new Date();
  let item = {
    id: count,
    name: one,
    price: two,
    qty: three,
    category: four,
  }
  products.push(item);
  this.setState({ exampleItems:products }); 
}

在开始进行修改之前,您需要复制状态。例如,将函数的第一行替换为:

let products = [...this.state.exampleItems];

注意:您在多个地方都有此问题,而不仅仅是handleAddEvent。我以该功能为例。为了解决问题,您可能需要修复所有导致状态突变的情况。