Why the result of ajax request doesn't set in Library which is [] by default.When the data of Library is set statically there would not be problem :
Library:[{'id': '5c0b6cd9e1382352759fbc25', 'hotelinfo': {'name': 'Korston Hotel', 'hotelsearch': {'realname': 'Korston Hotel Moscow', 'hotelid': 1011702.0, 'hotelimage': 'htl207110100001', 'countryid': 1002035.0, 'ecountryname': 'Russia', 'countryname': '', 'cityid': 1182348.0, 'ecityname': 'Moscow', 'cityname': '', 'star': 4.0, 'services': 'H.B', 'desc': ' ', 'enable': '1', 'delete': '0'}, 'information': {'viewname': ''}, 'validatedate': {'fdate': '1397-12-01', 'tdate': '1397-12-29', 'tdateid': 10592.0, 'fdateid': 10564.0}}, 'families': [{'availablerooms': [{'info': {'room': 'Single', 'cost': 2400.0, 'availability': 'onrequest', 'withbed': 0.0, 'withoutbed': 0.0, 'adults': 1.0, 'infant': 0.0, 'roomid': '1011702_483587', 'double': '0'}}], 'optionId': '1011702_483587###5c0b6cd9e1382352759fbc25', 'totalPrice': 2400.0, 'services': 'H.B', .....]
but Library is going to be dynamic and the data will be sent from another page to this page by ajax request.
What should I do to set the result of ajax request in Library.
class App extends React.Component {
constructor(props) {
super();
this.state = {
Library: [],
library: null,
perPage: 1,
currentPage: 1,
maxPage: null,
filter: ""
};
$.ajax({
url: "/json.bc",
type: "post",
data: {
cityid: "1182348",
rooms: JSON.stringify({ "rooms": [{ "adultcount": "1", "childcountandage": "0" }] }),
},
success: (result) => {
this.setState({ Library: eval(result) });
}
})
}
componentDidMount() {
this.reorganiseLibrary();
}
// Calculates the library
reorganiseLibrary = () => {
const { filter, perPage, Library } = this.state;
let library = Library;
console.log(Library) //There is no result here//
if (filter !== "") {
library = library.filter(item =>
item.hotelinfo.hotelsearch.realname.toLowerCase().includes(filter)
);
}
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
});
};
// Previous Page
previousPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage - 1
}));
// Next Page
nextPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage + 1
}));
// handle filter
handleFilter = evt =>
this.setState(
{
filter: evt.target.value.toLowerCase()
},
() => {
this.reorganiseLibrary();
}
);
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return <div>No results</div>;
}
return library[currentPage - 1].map(item => (
<div key={item.hotelinfo.hotelsearch.realname}>{item.hotelinfo.hotelsearch.realname}</div>
));
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div className="library">
<h1>Library</h1>
<div className="d-flex">
<div className="flex-fill">
<label className="library__filter-label">Filter</label>
<input value={this.state.filter} onChange={this.handleFilter} />
</div>
<div className="flex-fill text-right">
<label className="library__per-page-label">Per page</label>
<input placeholder="per page" value={this.state.perPage} onChange={this.handlePerPage} />
</div>
</div>
<div className="library__book-shelf">
{this.renderLibrary()}
</div>
<div className="d-flex">
<div className="flex-fill">
{currentPage !== 1 && (
<button onClick={this.previousPage}>Previous</button>
)}
</div>
<div className="flex-fill text-right">
{(currentPage < maxPage) && (
<button onClick={this.nextPage}>Next</button>
)}
</div>
</div>
<div className="library__page-info text-right">
{this.state.currentPage} of {this.state.maxPage}
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
First off, unless you really, really have to, try to avoid using jQuery in React. It's just going to lead to a massive headache.
You need to move that Ajax request out of the constructor and into your componentDidMount method. For example:
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
Library: [],
}
}
componentDidMount() {
fetch('/json.cs')
.then(response => response.json())
.then(data => {
this.setState(state => ({
...state,
Library: data
}), () => {
this.reorganiseLibrary()
})
}
}
}
You have to call Ajax to load remote content inside componentDidMount
componentDidMount() {
// call your ajax and set state
}
Moreover, you need to remove this.reorganiseLibrary(); inside componentDidMount or call it along with this.setState({ Library: eval(result) }); after calling ajax to improve performance.
Related
based on simple To-Do app, I'd like to understand how I can modify text of list item in place. List item contains 2 divs, first one holds todo's text and second one contains icons (delete, edit). I tried to conditionally render either first div or input inside the li, file ListItem.js, but that didn't work for me.
App.js
class App extends React.Component {
state = {
items: [],
currentValue: '',
clearValue: false
};
submitFormHandler = event => {
event.preventDefault();
if (this.state.currentValue === '') return;
const updatedItems = [...this.state.items];
if (
updatedItems.filter(udtItem => udtItem.value === this.state.currentValue)
.length === 0
) {
updatedItems.push({
id: uuidv4(),
value: this.state.currentValue,
completed: false
});
}
this.setState({ items: updatedItems, clearValue: true });
localStorage.setItem('todos', JSON.stringify(updatedItems));
};
changeInputHandler = event => {
this.setState({
currentValue: event.target.value,
clearValue: false
});
};
deleteItem = id => {
const updatedItems = [...this.state.items].filter(item => item.id !== id);
this.setState({ items: updatedItems });
localStorage.setItem('todos', JSON.stringify(updatedItems));
};
editItem = (event, id) => {
event.stopPropagation();
//do something here
};
deleteAll = () => {
this.setState({ items: [] });
localStorage.removeItem('todos');
};
componentDidMount() {
let todos = localStorage.getItem('todos');
if (todos) {
this.setState({ items: JSON.parse(todos) });
}
}
render() {
const itemList = this.state.items.map(item => (
<ListItem
key={item.id}
data={item}
deleted={this.deleteItem}
edited={this.editItem}
></ListItem>
));
return (
<div className="App">
<img src={trashIcon} alt="Delete" onClick={this.deleteAll} />
<header className="header">To-Do List</header>
<div className="items">
<ul>{itemList}</ul>
</div>
<form onSubmit={this.submitFormHandler}>
<Input
val={this.state.currentValue}
changed={e => this.changeInputHandler(e)}
clear={this.state.clearValue}
/>
</form>
</div>
);
}
}
export default App;
ListItem.js
class ListItem extends Component {
state = {
crossCheck: false,
hidden: true
};
toggleCrossCheck = () => {
const storageItems = JSON.parse(localStorage.getItem('todos'));
storageItems.forEach(item => {
if (item.id === this.props.data.id) {
item.completed = !item.completed;
this.setState({ crossCheck: item.completed });
}
});
localStorage.setItem('todos', JSON.stringify(storageItems));
};
componentDidMount() {
this.setState({ crossCheck: this.props.data.completed });
}
render() {
let classList = 'icon-container';
if (!this.state.hidden) classList = 'icon-container open';
return (
<li
className={this.state.crossCheck ? 'item cross-check' : 'item'}
onClick={this.toggleCrossCheck}
onMouseEnter={() => this.setState({ hidden: false })}
onMouseLeave={() => this.setState({ hidden: true })}
>
<div className="item-text">{this.props.data.value}</div>
<div className={classList}>
<Icon
iconType={trashIcon}
altText="Delete"
clicked={() => this.props.deleted(this.props.data.id)}
></Icon>
<Icon
iconType={editIcon}
altText="Edit"
clicked={event => this.props.edited(event, this.props.data.id)}
></Icon>
</div>
</li>
);
}
}
export default ListItem;
class Employee extends Component {
constructor() {
super();
this.state = {
// employees: employees,
employees: [],
searchfield: "",
currentPage: 1,
resultsPerPage: 50,
holder: [],
filteredEmployees: [],
value: "",
};
}
componentDidMount = async () => {
axios.get(`http://localhost:5000/`).then((res) => {
const employees = res.data;
this.setState({
employees: employees.recordsets[0],
holder: employees.recordsets[0],
});
});
};
onSearchChange = (event) => {
let { value } = event.target;
this.setState({ value }, () => {
var updatedList = this.state.holder;
updatedList = updatedList.filter((employee) => {
const fullName = employee.empFirstNm + " " + employee.empLastNm;
return (
fullName.toLowerCase().search(this.state.value.toLowerCase()) !== -1
);
});
this.setState({ employees: updatedList });
});
};
//change page
onPaginate = (pageNumber) => {
this.setState({ currentPage: pageNumber });
};
render() {
const { employees, searchfield, currentPage, resultsPerPage } = this.state;
const { onRouteChange } = this.props;
//Get current employees
const indexOfLastEmployee = currentPage * resultsPerPage;
const indexOfFirstEmployee = indexOfLastEmployee - resultsPerPage;
console.log("indexOfFirstEmployee: ", indexOfFirstEmployee);
console.log("indexOfLastEmployee: ", indexOfLastEmployee);
const filteredEmployees = employees.slice(
indexOfFirstEmployee,
indexOfLastEmployee
);
return !employees.length ? (
<div className="tc">
<h1>Loading</h1>
<Spinner animation="border" variant="danger" />
</div>
) : (
<FadeIn>
<div className="tc">
<div
className="
d-flex
justify-content-between
flex-wrap
flex-md-nowrap
align-items-center
pt-3
pb-2
mb-3
border-bottom"
>
<h1 className="display-2">Employees</h1>
<div
className="tr"
style={{
margin: "15px 0",
}}
>
<NewEmployee employees={employees} />
<SearchBox
searchChange={this.onSearchChange}
value={this.state.value}
/>
</div>
</div>
<Scroll>
<CardList
employees={filteredEmployees}
onDelete={this.handleDelete}
onRouteChange={onRouteChange}
/>
<Table
employees={filteredEmployees}
onRouteChange={onRouteChange}
/>
<Pagination
resultsPerPage={resultsPerPage}
totalResults={employees.length}
onPaginate={this.onPaginate}
/>
</Scroll>
</div>
</FadeIn>
);
}
}
I have tried implementing it with conditions of whether the results
is greater than or equal to the results on a page but it did not
work since it doesnt cover every single case based on the result.
I am getting the search to work but when my current page is anything besides 1 is when the search doesn't work.
Any idea how I can get the filtering to work regardless of what page I
am on?
Figured this out. I just needed to set currentPage to 1 at the end of my search:
onSearchChange = (event) => {
let { value } = event.target;
this.setState({ value }, () => {
//running this after setting the value in state because of async
var updatedList = this.state.holder;
updatedList = updatedList.filter((employee) => {
const fullName = employee.empFirstNm + " " + employee.empLastNm;
return (
fullName.toLowerCase().search(this.state.value.toLowerCase()) !== -1
);
});
this.setState({ employees: updatedList });
this.setState({ currentPage: 1 });
});
I have a series of data that contains some objects in an array(json file) and it will be shown by fetch request.There is a renderMaxTotal() function that must get me the max number of in totalcomof all data of json file but it shows me the max number of in totalcom in the current page and by going to another page the amount of renderMaxTotal() will be changed.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
library: null,
perPage: 20,
currentPage: 1,
maxPage: null,
};
}
componentDidMount() {
fetch('/json.bc', {
method: 'get',
})
.then(response => response.text())
.then(text => {
let Maindata = JSON.parse(text.replace(/\'/g, '"'))
this.setState(state => ({
...state,
data: Maindata
}), () => {
this.reorganiseLibrary()
})
}).catch(error => console.error(error))
}
reorganiseLibrary = () => {
const { perPage, data } = this.state;
let library = data;
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
})
}
// Previous Page
previousPage = event => {
this.setState({
currentPage: this.state.currentPage - 1
})
}
// Next Page
nextPage = event => {
this.setState({
currentPage: this.state.currentPage + 1
})
}
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return <div className="nodata">No Result</div>
}
return library[currentPage - 1].sort((a, b) => a.total - b.total).map((item, i) => (
<div className="item">
<span>{this.renderTotalcom(item)}</span>
</div>
))
}
// handle render of library
renderMaxTotal = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return <div className="nodata">No Result</div>
}
return Math.max(...library[currentPage].map(item => item.totalCom))
}
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
<span className="max">{this.renderMaxTotal()}</span>
{this.renderLibrary()}
<ul id="page-numbers">
<li className="nexprevPage">
{currentPage !== 1 && (
<button onClick={this.previousPage}><span className="fa-backward"></span></button>
)}
</li>
<li className="controlsPage active">{this.state.currentPage}</li>
<li className="restControls">...</li>
<li className="controlsPage">{this.state.maxPage}</li>
<li className="nexprevPage">
{(currentPage < maxPage) && (<button onClick={this.nextPage}><span className="fa-forward"></span></button>
)}
</li>
</ul>
</div>
)
}
renderTotalcom(element) {
console.log(typeof element.totalCom)
return element.totalCom
}
}
ReactDOM.render(<App />, document.getElementById('Result'))
If I change renderMaxTotal() to this:
Math.max(...library[0].map(item=>item.totalCom))
it will show me the max of first page and by turning to another page it does not change.
If I change renderMaxTotal() to this:
Math.max(...library.map(item=>item.totalCom))
it will be NaN.
How can I have the max amount of totalcom in whole pages?
The code below will get the max of each pages and compare it with the current Max.
// handle render of library
renderMaxTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return <div className="nodata">No Result</div>
}
return library.reduce((acc,lib)=>{
const libMax = Math.max(...lib.map(item => item.totalCom))
return libMax > acc ? libMax : acc
},0)
}
The code below shows each user info on users list button click.
Now I want fetch each users record from database on users list button click.
In the open() function, I have implemented the code below
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
}
In class OpenedUser(), I have initialize in the constructor the code below
chatData: []
In the render method have implemented the code
<b> Load Message from Database for each user ({this.state.chatData1})</b>
<div>
{this.state.chatData.map((pere, i) => (<li key={i}>{pere.lastname} - {pere.id}----- {pere.username}</li>))}
</div>
Here is my Issue:
My problem is that the Axios Api is getting the result but am not seeing any result in the render method.
but I can see it in the console as per code below
Array(1)
0: {id: "1", firstname: "faco", lastname: "facoyo"}
length: 1
Here is an example of json api response.
[{"id":"1","firstname":"faco","lastname":"facoyo"}]
Here is the full code
import React, { Component, Fragment } from "react";
import { render } from "react-dom";
import { Link } from 'react-router-dom';
import axios from 'axios';
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button onClick={() => this.open(this.props.data.id,this.props.data.name)}>{this.props.data.name}</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
chatData: [],
hidden: false,
};
}
componentDidMount(){
} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b> Load Message from Database for each user ({this.state.chatData1}) </b>
<div>
{this.state.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</div>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
],
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id,name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: 'id',
uname: 'name'
};
this.setState({ loading_image: true }, () => {
axios.post("http://localhost/apidb_react/search_data.php", { user_data })
.then(response => {
this.setState({
chatData1: response.data[0].id,
chatData: response.data,
loading_image: false
});
console.log(this.state.chatData);
alert(this.state.chatData1);
})
.catch(error => {
console.log(error);
});
});
// end axios api call
this.setState((prevState) => ({
activeIds: prevState.activeIds.find((user) => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
}
close = id => {
this.setState((prevState) => ({
activeIds: prevState.activeIds.filter((user) => user !== id),
}));
};
renderUser = (id) => {
const user = this.state.data.find((user) => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser key={user.id} data={user} close={this.close}/>
)
}
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map((id) => this.renderUser(id)) }
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
The problem is you're making the request in the App component and storing in state but you're trying to access the state in a child component so it will never actually read the data.
To fix this you need to pass in the chat data via prop
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
Note: In my runnable example, I've replaced your api endpoint with a mock api promise.
const mockApi = () => {
return new Promise((resolve, reject) => {
const json = [{ id: "1", firstname: "faco", lastname: "facoyo" }];
resolve(json);
});
};
class User extends React.Component {
open = () => this.props.open(this.props.data.id, this.props.data.name);
render() {
return (
<React.Fragment>
<div key={this.props.data.id}>
<button
onClick={() => this.open(this.props.data.id, this.props.data.name)}
>
{this.props.data.name}
</button>
</div>
</React.Fragment>
);
}
}
class OpenedUser extends React.Component {
constructor(props) {
super(props);
this.state = {
hidden: false
};
}
componentDidMount() {} // close component didmount
toggleHidden = () =>
this.setState(prevState => ({ hidden: !prevState.hidden }));
close = () => this.props.close(this.props.data.id);
render() {
return (
<div key={this.props.data.id} style={{ display: "inline-block" }}>
<div className="msg_head">
<button onClick={this.close}>close</button>
<div>user {this.props.data.id}</div>
<div>name {this.props.data.name}</div>
{this.state.hidden ? null : (
<div className="msg_wrap">
<div className="msg_body">Message will appear here</div>
<b>
{" "}
Load Message from Database for each user ({this.state.chatData1}
){" "}
</b>
<ul>
{this.props.chatData.map((pere, i) => (
<li key={i}>
{pere.lastname} - {pere.id}----- {pere.username}
</li>
))}
</ul>
</div>
)}
</div>
</div>
);
}
}
class App extends React.Component {
constructor() {
super();
this.state = {
shown: true,
chatData: [],
activeIds: [],
data: [
{ id: 1, name: "user 1" },
{ id: 2, name: "user 2" },
{ id: 3, name: "user 3" },
{ id: 4, name: "user 4" },
{ id: 5, name: "user 5" }
]
};
}
toggle() {
this.setState({
shown: !this.state.shown
});
}
open = (id, name) => {
alert(id);
alert(name);
//start axios api call
const user_data = {
uid: "id",
uname: "name"
};
// this.setState({ loading_image: true }, () => {
// axios
// .post("http://localhost/apidb_react/search_data.php", { user_data })
// .then(response => {
// this.setState({
// chatData1: response.data[0].id,
// chatData: response.data,
// loading_image: false
// });
// console.log(this.state.chatData);
// alert(this.state.chatData1);
// })
// .catch(error => {
// console.log(error);
// });
// });
this.setState({ loading_image: true }, () => {
mockApi().then(data => {
this.setState({
chatData1: data[0].id,
chatData: data,
loading_image: false
});
});
});
// end axios api call
this.setState(prevState => ({
activeIds: prevState.activeIds.find(user => user === id)
? prevState.activeIds
: [...prevState.activeIds, id]
}));
};
close = id => {
this.setState(prevState => ({
activeIds: prevState.activeIds.filter(user => user !== id)
}));
};
renderUser = id => {
const user = this.state.data.find(user => user.id === id);
if (!user) {
return null;
}
return (
<OpenedUser
chatData={this.state.chatData}
key={user.id}
data={user}
close={this.close}
/>
);
};
renderActiveUser = () => {
return (
<div style={{ position: "fixed", bottom: 0, right: 0 }}>
{this.state.activeIds.map(id => this.renderUser(id))}
</div>
);
};
render() {
return (
<div>
{this.state.data.map(person => (
<User key={person.id} data={person} open={this.open} />
))}
{this.state.activeIds.length !== 0 && this.renderActiveUser()}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
I see a few missing points in your code namely you are using li without ul which is a kind of invalid markup, then you have mapping for .username which is undefined field according to response which may also throw error.
I have got series of data that contains some objects in one array(json file) and it will be shown by react.
const Library = [
{
name: "Star Wars"
},
{
name: "Harry Potter"
},
{
name: "Lord of the Rings"
},
{
name: "Star Trek"
},
{
name: "The Fault in Our Stars"
},
{
name: "Number the Stars"
},
{
name: "Blue"
},
{
name: "Act Da Fool"
},
{
name: "The Gilded Cage"
},
{
name:
"To Get to Heaven First You Have to Die (Bihisht faqat baroi murdagon)"
},
{
name: "Lebanon"
},
{
name: "Tenderness"
},
{
name: "It"
},
{
name: "Locked Out (Enfermés dehors)"
},
{
name: "Waterloo Bridge"
},
{
name: "Set It Off"
},
{
name: "Nil By Mouth"
},
{
name: "Monte Carlo"
},
{
name: "Treasure of the Four Crowns"
},
{
name: "Donnie Darko"
},
{
name: "Cry-Baby"
},
{
name: "Juan of the Dead (Juan de los Muertos)"
},
{
name: "Constant Nymph, The"
}
];
// Main App Component
class App extends React.Component {
constructor(props){
super();
this.state = {
library: null,
perPage: 1,
currentPage: 1,
maxPage: null,
filter: ""
};
}
componentDidMount() {
this.reorganiseLibrary();
}
// Calculates the library
reorganiseLibrary = () => {
const { filter, perPage } = this.state;
let library = Library;
console.log(library)
if (filter !== "") {
library = library.filter(item =>
item.hotelinfo.hotelsearch.realname.toLowerCase().includes(filter)
);
}
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
});
};
// Previous Page
previousPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage - 1
}));
// Next Page
nextPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage + 1
}));
// handle filter
handleFilter = evt =>
this.setState(
{
filter: evt.target.value.toLowerCase()
},
() => {
this.reorganiseLibrary();
}
);
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return <div>No results</div>;
}
return library[currentPage - 1].map(item => (
<div key={item.hotelinfo.hotelsearch.realname}>{item.hotelinfo.hotelsearch.realname}</div>
));
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div className="library">
<h1>Library</h1>
<div className="d-flex">
<div className="flex-fill">
<label className="library__filter-label">Filter</label>
<input value={this.state.filter} onChange={this.handleFilter} />
</div>
<div className="flex-fill text-right">
<label className="library__per-page-label">Per page</label>
<input placeholder="per page" value={this.state.perPage} onChange={this.handlePerPage} />
</div>
</div>
<div className="library__book-shelf">
{this.renderLibrary()}
</div>
<div className="d-flex">
<div className="flex-fill">
{currentPage !== 1 && (
<button onClick={this.previousPage}>Previous</button>
)}
</div>
<div className="flex-fill text-right">
{(currentPage < maxPage) && (
<button onClick={this.nextPage}>Next</button>
)}
</div>
</div>
<div className="library__page-info text-right">
{this.state.currentPage} of {this.state.maxPage}
</div>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
The data of Library is going to be dynamic and the data will be sent from another page to this page by ajax request but as you can see data is set statically. How to set data of Library dynamiclly.
I try below code biy there is this error :
ReferenceError: Library is not defined
Component {
constructor(props){
super();
this.state = {
Library:[],
library: null,
.....
};
$.ajax({
url:"/json.bc",
type:"post",
data:{
cityid:"1182348",
rooms:JSON.stringify({"rooms":[{"adultcount":"1","childcountandage":"0"}]}),
},
success:(result)=>{
this.setState({Library: eval(result)}); } }) }
. . .
}
Edited code :
class App extends React.Component {
constructor(props){
super();
this.state = {
Library:[],
library: null,
perPage: 1,
currentPage: 1,
maxPage: null,
filter: "",
};
}
componentDidMount() {
$.ajax({
url:"/test1.bc",
type:"post",
data:{
cityid:"1182348",
rooms:JSON.stringify({"rooms":[{"adultcount":"1","childcountandage":"0"}]}),
},
success:(result)=>{
this.setState({Library: eval(result)}); }
})}
componentDidMount() {
this.reorganiseLibrary();
}
// Calculates the library
reorganiseLibrary = () => {
const { filter, perPage } = this.state;
let library = Library;
console.log(library)
if (filter !== "") {
library = library.filter(item =>
item.hotelinfo.hotelsearch.realname.toLowerCase().includes(filter)
);
}
library = _.chunk(library, perPage);
this.setState({
library,
currentPage: 1,
maxPage: library.length === 0 ? 1 : library.length
});
};
// Previous Page
previousPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage - 1
}));
// Next Page
nextPage = () =>
this.setState(prevState => ({
currentPage: prevState.currentPage + 1
}));
// handle filter
handleFilter = evt =>
this.setState(
{
filter: evt.target.value.toLowerCase()
},
() => {
this.reorganiseLibrary();
}
);
// handle per page
handlePerPage = (evt) =>
this.setState({
perPage: evt.target.value
}, () => this.reorganiseLibrary());
// handle render of library
renderLibrary = () => {
const { library, currentPage } = this.state;
if (!library || (library && library.length === 0)) {
return <div>No results</div>;
}
return library[currentPage - 1].map(item => (
<div key={item.hotelinfo.hotelsearch.realname}>{item.hotelinfo.hotelsearch.realname}</div>
));
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div className="library">
<h1>Library</h1>
<div className="d-flex">
<div className="flex-fill">
<label className="library__filter-label">Filter</label>
<input value={this.state.filter} onChange={this.handleFilter} />
</div>
<div className="flex-fill text-right">
<label className="library__per-page-label">Per page</label>
<input placeholder="per page" value={this.state.perPage} onChange={this.handlePerPage} />
</div>
</div>
<div className="library__book-shelf">
{this.renderLibrary()}
</div>
<div className="d-flex">
<div className="flex-fill">
{currentPage !== 1 && (
<button onClick={this.previousPage}>Previous</button>
)}
</div>
<div className="flex-fill text-right">
{(currentPage < maxPage) && (
<button onClick={this.nextPage}>Next</button>
)}
</div>
</div>
<div className="library__page-info text-right">
{this.state.currentPage} of {this.state.maxPage}
</div>
</div>
);
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
You can try this:
getData = (callback) => {
$.ajax({
url:"/json.bc",
type:"post",
data:{
cityid:"1182348",
rooms:JSON.stringify({"rooms":[{"adultcount":"1","childcountandage":"0"}]}),
},
success:(result)=>{
callback(eval(result))
}
. . .
}
}
setData = () => {
this.getData(data => { this.setState({ Library: data }) } )
}
Try calling the ajax call in componentDidMount() set state.
componentDidMount() {
$.ajax({
url:"/json.bc",
type:"post",
data:{
cityid:"1182348",
rooms:JSON.stringify({"rooms":[{"adultcount":"1","childcountandage":"0"}]}),
},
success:(result)=>{
this.setState({Library: eval(result)}); } }) }
. . .
}
}