How to set a default value into a prop in ReactJs? - reactjs

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 renderMinTotal() function that must get me the min number of in totalcomof all data of json file.This function works correctly but I want the default value of FilterTotal be the result of renderMinTotal().For this I write this code :
let defaultFilterTotal = null;
defaultFilterTotal = FilterTotal
? (FilterTotal)
: (this.renderMinTotal ());
but the default value is empty. Why it is not been set as default value of
FilterTotal?
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
library: null,
perPage: 20,
currentPage: 1,
maxPage: null,
FilterTotal: "",
};
}
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 { FilterTotal, perPage, data } = this.state;
let library = data;
let defaultFilterTotal = null;
defaultFilterTotal = FilterTotal
? (FilterTotal)
: (this.renderMinTotal()); //The default value of FilterTotal is not been set .////
if (FilterTotal !== "") {
library = library.filter(item =>
item.totalCom > FilterTotal
)
}
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
renderMinTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return ''
}
return library.reduce((acc, lib) => {
const libMin = Math.min(...lib.map(item => item.totalCom))
return acc === undefined ? libMin : libMin < acc ? libMin : acc
}, undefined)
}
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
<span className="max">{this.renderMinTotal()}</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) {
return element.totalCom
}
}
ReactDOM.render(<App />, document.getElementById('Result'))

The code returns this if there's no library, so it will be an empty string just like how this.state.FilterTotal is originally an empty string
if (!library || (library && library.length === 0)) {
return ''
}

Related

Access to api response data

My code pass in a search term and the promise api call returns one record and the data format is as below:
` json api data
0:
{
id:"aff3b4fa-bdc0-47d1-947f-0163ff5bea06"
keyword: somekeyword
URL:"mypage.html"
}
I need to retrieve the URL value, so I try to get URL by using response.data[0].URL. But I receive the error "Unhandled Rejection (TypeError): response.data[0] is undefined". How do I get the URL value? Thanks.
` autocomplete.js
export class Autocomplete extends Component {
state = {
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: "",
suggestions: [],
results: [],
URL: "",
};
componentDidMount() {
this.GetPrograms();
const { userInput } = this.state;
//this.runSearch();
}
GetPrograms = () => {
axios
.get("https://mydomain/GetPrograms/")
.then((response) => {
this.setState({ suggestions: response.data });
});
};
runSearch = async () => {
const response = await axios.get(
"https://mydomain/api/get",
{
params: {
searchTerm: this.state.userInput,
},
}
);
let results = response.data;
console.log("response", results);
this.setState({ results: results, URL: response.data[0].URL });
window.location.href =
"https://mydomain/" + this.state.URL;
};
onChange = (e) => {
const { suggestions } = this.state; //this.props;
const userInput = e.currentTarget.value;
const filteredSuggestions = suggestions.filter(
(suggestion) =>
suggestion.toLowerCase().indexOf(userInput.toLowerCase()) > -1
);
this.setState({
activeSuggestion: 0,
filteredSuggestions,
showSuggestions: true,
userInput: e.currentTarget.value,
});
};
onClick = (e) => {
this.setState({
activeSuggestion: 0,
filteredSuggestions: [],
showSuggestions: false,
userInput: e.currentTarget.innerText,
});
this.onSearch();
console.log(
"child component clicked and value=" + e.currentTarget.innerText
);
};
onKeyDown = (e) => {
const { activeSuggestion, filteredSuggestions } = this.state;
if (e.keyCode === 13) {
this.setState({
activeSuggestion: 0,
showSuggestions: false,
userInput: filteredSuggestions[activeSuggestion],
});
} else if (e.keyCode === 38) {
if (activeSuggestion === 0) {
return;
}
this.setState({ activeSuggestion: activeSuggestion - 1 });
} else if (e.keyCode === 40) {
if (activeSuggestion - 1 === filteredSuggestions.length) {
return;
}
this.setState({ activeSuggestion: activeSuggestion + 1 });
}
//this.setState({ searchTerm: e.currentTarget.value });
console.log("userinput:" + this.state.userInput);
};
render() {
const {
onChange,
onClick,
onKeyDown,
onKeyPress,
state: {
activeSuggestion,
filteredSuggestions,
showSuggestions,
userInput,
},
} = this;
let suggestionsListComponent;
if (showSuggestions && userInput) {
if (filteredSuggestions.length) {
suggestionsListComponent = (
<ul class="suggestions">
{filteredSuggestions.map((suggestion, index) => {
let className;
if (index === activeSuggestion) {
className = "";
}
return (
<li key={suggestion} onClick={onClick}>
{suggestion}
</li>
);
})}
</ul>
);
} else {
suggestionsListComponent = (
<div class="no-suggestions">
<em>No suggestions</em>
</div>
);
}
}
return (
<div>
<input
id="search-box"
placeholder="Search..."
type="search"
onChange={onChange}
onKeyDown={onKeyDown}
value={userInput}
/>
{suggestionsListComponent}
</div>
);
}
}
export default Autocomplete;
`
The api call returns 0 record that causes the error.

React class component button setState sorting not working as intended

import AuthorSidebar from "../SubPages/AuthorSidebar";
import ReactPaginate from 'react-paginate';
import { Card, Button } from 'react-bootstrap';
export default class Author extends React.Component {
constructor(props) {
super(props);
this.state = {
author: [],
AuthorTempState: [],
selectedPage: 0,
Postsperpage: 4,
PagesVisited: 0
}
this.handlePageClick = this.handlePageClick.bind(this);
}
async recievedData() {
const res = await fetch(`https://api.quotable.io/authors?limit=30`);
const data = await res.json();
for (const element of data.results) {
element.idfav = false;
}
data.results.sort((a, b) => (a._id > b._id) ? 1 : -1)
this.setState({
author: data.results,
AuthorTempState: data.results
});
}
componentDidMount() {
if (localStorage.getItem('authors')) {
this.setState({
author: JSON.parse(localStorage.getItem('authors')),
AuthorTempState: JSON.parse(localStorage.getItem('authors'))
})
} else {
this.recievedData();
}
}
componentDidUpdate(prevProps, prevState) {
if (this.state.author !== prevState.author) {
localStorage.setItem('authors', JSON.stringify(this.state.author))
}
}
favBttn(Auth) {
const filterData = this.state.AuthorTempState.filter(data => data._id !== Auth._id)
Auth.idfav = true;
const updateAuthor = [Auth, ...filterData];
updateAuthor.sort((a, b) => (a._id > b._id) ? 1 : -1)
this.setState({
author: updateAuthor
});
}
remfavBttn(Auth) {
const filterData = this.state.AuthorTempState.filter(data => data._id !== Auth._id)
Auth.idfav = false;
const updateAuthor = [Auth, ...filterData]
updateAuthor.sort((a, b) => (a._id > b._id) ? 1 : -1)
this.setState({
author: updateAuthor
});
}
handlePageClick = (e) => {
const SelectedPage = e.selected;
const Offset = SelectedPage * this.state.Postsperpage;
this.setState({
selectedPage: SelectedPage,
PagesVisited: Offset
}, () => {
this.recievedData();
});
};
render() {
const { author } = this.state;
const PageCount = Math.ceil(author.length / this.state.Postsperpage);
console.log(author)
let sliced = author.slice(this.state.PagesVisited, this.state.PagesVisited + this.state.Postsperpage);
return (
<div className="AppWhole">
<AuthorSidebar />
<div className="App">
<div className="author">
{sliced.map(
(Author) => (
<div key={Author._id}>
<Card style={{ margin: 20 }} border="dark" bg="light" text="grey">
<Card.Body>
<Card.Title>Name: {Author.name}
{
(Author.idfav) ? (<Button size="sm" className='right' onClick={() =>
this.remfavBttn(Author)
}>Remove Favt.</Button >) : (<Button size="sm" className='right' onClick={() =>
this.favBttn(Author)
}>Add Favt.</Button >)
}
</Card.Title>
<Card.Text>
Bio: {Author.bio}
</Card.Text>
</Card.Body>
<Card.Footer>Wiki: <a href='{Author.link}'>{Author.link}</a></Card.Footer>
</Card>
</div>
))}
<div >
<ReactPaginate
pageCount={PageCount}
onPageChange={this.handlePageClick}
previousLabel={"<<"}
nextLabel={">>"}
containerClassName={'paginationLinks'}
disabledClassName={'paginationDisabled'}
activeClassName={'paginationActive'}
/>
</div>
</div>
</div>
</div>
);
}
}
So my page is an Author page which shows different authors and their details in each card which I fetched from API and then mapped. https://i.stack.imgur.com/QitTe.png
And in each card after onclick it changes to Remove Favourite. The card which is favourited makes the idfav true in the object array of the author state and false if not favourited. And there is a 2nd page which shows all the favourite authors. Now after clicking once on a card to remove fav and then clicking another card also to remove favourite the former card gets turned to add favourite automatically.
Please help me I have been stuck on this for 2 weeks now. Thank you.
Since you need to update a single object in-place in a list, here's how you do that really simply.
const bttn = (idfav) => Auth => this.setState({
author: this.state.author.map(a =>
a._id === Auth._id
// When we find the auth to update, change its idfav
? {...a, idfav }
: a
});
const favBttn = bttn(true);
const remfavBttn = bttn(false);
Or if you prefer the undried version:
function async favBttn(Auth) {
this.setState({
author: this.state.author.map(a =>
a._id === Auth._id
// When we find the auth to update, change its idfav
? {...a, idfav: true }
: a
});
}
function async favBttn(Auth) {
this.setState({
author: this.state.author.map(a =>
a._id === Auth._id
// When we find the auth to update, change its idfav
? {...a, idfav: false }
: a
});
}

Sorting an array that is in another array in ReactJs

I have a json file called by fetch request that looks like this:
[
{
"Infos": [
{
"id": {
"Id": "105254"
},
"total": 142854739
},
{
"id": {
"Id": "105255"
},
"total": 112854739
},
{
"id": {
"Id": "105256"
},
"total": 132854739
},
{
"id": {
"Id": "106540"
},
"total": 122868818
}
]
}
]
I want to sort data based on total field ,but as you can see all objects are in another array called Infos and I can not to sort data like this:
Maindata.sort((a, b) => a.total - b.total);
How can I sort data based on total field that is in another an array?
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, '"'))
Maindata.sort((a, b) => a.Infos[i].total - b.Infos[i].total) // I want to sort data here /////
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>NOResult</div>
}
return library[currentPage - 1].map((item, i) => (
<div className="Wrapper">{this.renderInfo(item)}</div>
))
}
renderInfo(element){
let len =element.Infos.length
for (let i = 0; i < len; i++) {
return element.Infos[i].total
}
}
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
{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 activeCnt">{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>
)
}
}
ReactDOM.render(<App />, document.getElementById('Result'))
You can sort the inner field by mapping over the outer array and sorting the inner one like
Maindata = Maindata.map((data) => ({Infos: data.Infos.sort((a, b) => a.total - b.total)}))

Finding Maximum value in an Array of Objects by ReactJs

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)
}

DefaultValue in input by type=range

I have an Input by type=range that the value of min , max and defaultvalue would be set by {this.renderMinTotal()} and {this.renderMaxTotal()} and as you can see the value of defaultvalue is the output of {this.renderMaxTotal()} but the thumb of input looks that the value of defaultvalue is {this.renderMinTotal()} while the value of defaultvalue is {this.renderMaxTotal()} and in inspector the values of min , max and defaultvalue are correct.
The output of input in inspector:
<input type="range" min="17386000" max="178124000" step="1000" class="multirange" value="178124000">
It must be like this:
=============[]
while it looks like this:
[]=============
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">NoResult</div>;
}
return library[currentPage - 1]
.sort((a, b) => a.total - b.total)
.map((item, i) => (
<div className="item">
<span>{item._id.value} </span>
</div>
));
};
renderMinTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return "";
}
return library.reduce((acc, lib) => {
const libMin = Math.min(...lib.map(item => item.totalCom));
return acc === undefined ? libMin : libMin < acc ? libMin : acc;
}, undefined);
};
renderMaxTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return "";
}
return library.reduce((acc, lib) => {
const libMax = Math.max(...lib.map(item => item.totalCom));
return libMax > acc ? libMax : acc;
}, 0);
};
render() {
const { library, currentPage, perPage, maxPage } = this.state;
return (
<div>
<div>
<input
type="range"
min={this.renderMinTotal()}
max={this.renderMaxTotal()}
defaultValue={this.renderMaxTotal()}
step="1000"
className="multirange"
/>
</div>
{this.renderLibrary()}
<ul id="page-numbers">
<li className="nexprevPage">
{currentPage !== 1 && (
<button onClick={this.previousPage}>
<span className="fa-backward" />
</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" />
</button>
)}
</li>
</ul>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('Result'))
Edited Code:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
library: 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 { data } = this.state;
let library = data;
library = _.chunk(library);
this.setState({
library,
});
};
// handle per page
handlePerPage = evt =>
this.setState(
{
perPage: evt.target.value
},
() => this.reorganiseLibrary()
);
renderMinTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return "";
}
return library.reduce((acc, lib) => {
const libMin = Math.min(...lib.map(item => item.totalCom));
return acc === undefined ? libMin : libMin < acc ? libMin : acc;
}, undefined);
};
renderMaxTotal = () => {
const { library } = this.state;
if (!library || (library && library.length === 0)) {
return "";
}
return library.reduce((acc, lib) => {
const libMax = Math.max(...lib.map(item => item.totalCom));
return libMax > acc ? libMax : acc;
}, 0);
};
render() {
const { library } = this.state;
return (
<div>
<div>
<input
type="range"
min={this.renderMinTotal()}
max={this.renderMaxTotal()}
defaultValue={this.renderMaxTotal()}
step="1000"
className="multirange"
/>
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('Result'))

Resources