Reputation: 21
I have added sorting facility in my table. While I sort or delete an element, 2 arrays are coming same, one of prevprops and another of current props. I reviewed my code and found error coming from following piece of code.
Here is my Pagination.js code
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
Here is my App.js code
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>
);
}
}
Can you please tell me, where I should change my code ?
Upvotes: 2
Views: 2643
Reputation: 84982
You have several instances where you are mutating the state. In react, your state needs to be immutable, otherwise it's not possible to compare before and after, because before and after are the same thing. For example, you have this code here:
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 });
}
You need to make a copy of the state before you start making modifications. For example, replace the first line of the function with:
let products = [...this.state.exampleItems];
Note: You have this issue in multiple places, not just handleAddEvent. I show that function just as an example. You'll probably need to fix all cases where you're mutating state in order to resolve your issue.
Upvotes: 2