How to load more content from server on Scroll in reactjs - reactjs

I want to call API and load more item from database using scroll, initially, I want to display five record only, then if user scroll and reach bottom of scroll then I want to display five more record. it is about to lazy loading.
Please I am new to reactjs how can I achieve it.
this is the my code.
{this.state.selected ==='text' && <div style={{overflow:'auto', height:'200px'}} data-tab-content="tab2">
{this.state.textList.length>0 ? this.state.textList.map(text=>
<p >{text.text} </p>
):<p>no record found</p>} */}
</div>}
Here I am making
// get Text List
getTextList(){
debugger
fetch(baseUrl +`/language/listtext/${'1'}/${'5'}/${this.state.lesson_id}/${this.state.premiumprice_id}`)
.then(response => response.json())
.then(data => {
debugger
if(data.status ===200){
debugger
this.setState({
textList: data.text.docs,
})
}else{
this.setState({textList : []})
}
})
}
Thank in advance

Add onScroll event on div like
// for example <div onScroll={this.handleScroll}/>
handleScroll = (e) => {
const bottom = Number((e.target.scrollHeight - e.target.scrollTop).toFixed(0)) - e.target.clientHeight < 50;
let page = this.state.page;
if (bottom) {
// write fetching logic here...
}
};

Related

Next.js refresh values without reloading page in props list

probably I got a little bit lost on the following task. I have an admin page in my application where you can see all the posts from the plattform. I'm requesting the posts from an api and Im displaying them on the page as a list. I Inserted two buttons to enable/disable the post by calling a function which does tag the post to be enabled/disabled.
Everything works fine, but I want to change the state of the button without reloading the page. Im passing disable parameter threw the button tag. I don't know why its not working, if I console.log the values its already changed there. Is this a proper way to use useeffect? I tried to use it but I failed using it correct.
Somebody can help please?
Simplified Code ( I removed the enable function, since its nearly the same like disable)
export default function Feed(props) {
const [postStatus, setPostStatus] = useState(props.posts)
async function disablePost(id, e){
e.preventDefault();
const userInput = { postId: id }
try{
const res = await axios.post(`${baseurl}/api/auth/admin/disable-post`, userInput, {
})
var currentPostStatus = postStatus;
currentPostStatus.map((el) => {
if(el.id === id){
el.disabled = true;
}
console.log(el.id)
});
setPostStatus(currentPostStatus)
console.log(postStatus)
}catch(error){
console.log(error)
return
}
}
return (
<>
<HeaderAdmin></HeaderAdmin>
<div>
{/* {console.log(props.userCount)} */}
<p>Alle Posts</p>
{postStatus.map((post) =>
<React.Fragment key={post.id}>
<p>{post.id}</p>
<p>{post.email}</p>
<p>{post.desc}</p>
<p>{post.disabled == true ? 'Post deaktviert' : 'Post aktiviert'}</p>
<button disabled={ post.disabled } onClick={(e) => disablePost(post.id, e)}>Post deaktivieren</button>
<button disabled={ !post.disabled } onClick={(e) => enablePost(post.id, e)}>Post aktivieren</button>
</React.Fragment>
)}
</div>
</>
);
}
Your screen can't refresh to the new version after you clicked the disable or enable.
var currentPostStatus = postStatus;
currentPostStatus.map((el) => {
if(el.id === id){
el.disabled = true;
}
});
In your code, you are only changing the internal property of postStatus, but React only cares about the reference of the object. so you need to do
setPostStatus([...currentPostStatus])
The above line create a new array. I personally believe this is something React should improve in the future, because half of the question about React in stackoverflow is talking about this :)

Ionic w/ React Trigger Infinite Scroll until the page is filled

I have the following component.
const Feed: React.FC<FeedProps> = memo((props) => {
// ... lines skipped for brevity
return (
<div>
<IonList>
{
data.map((item) => {
return <FeedItem key={item.id!} item={item} />
})
}
</IonList>
<IonInfiniteScroll onIonInfinite={(e: CustomEvent<void>) => __handleIonInfinite(e)}>
<IonInfiniteScrollContent loadingText="Loading items" />
</IonInfiniteScroll>
</div>
);
async function __handleIonInfinite(e: CustomEvent<void>) {
const result = await __get();
if (result && result.length < environment.PAGE_SIZE) {
(e.target as HTMLIonInfiniteScrollElement).disabled = true;
}
(e.target as HTMLIonInfiniteScrollElement).complete();
}
});
Everything works fine when scrolling. I have one question though. At first, the page is empty and I need to scroll to trigger the event. I was wondering if there is a way of triggering the scroll event such that it fills the page?
I was thinking of implementing this myself but maybe it comes out of the box? Besides, it tends to be a little complex because, depending on your screen size, I would need to see how many times I should trigger this.

How to load images from firebase to carousel react?

I'm trying to get some images from firebase storage loaded into a react-responsive-carousel. The problem is that only 1 or 2 or even none of the images are loaded (there are at least 10 images). This is what I'm trying:
const [imagenes, setImagenes] = useState([]);
useEffect(() => {
const fetchedImagenes = [];
firebase.storage().ref().child('PR/Gallery').listAll().then(function (result) {
result.items.forEach(function (itemRef) {
itemRef.getDownloadURL().then(function (link) {
const fetchedImagen = link
fetchedImagenes.push(fetchedImagen)
})
});
setImagenes(fetchedImagenes)
})
}, [])
And this is the carousel code:
<Carousel dynamicHeight={true}>
{imagenes.map(imagen => {
return <div>
<img src={imagen} />
</div>
})}
</Carousel>
My guess is that the imagenes array is not filled when I show the images, so is there any way that I can wait for the imagenes array to be filled and then show the images?
You're now calling setImagenes(fetchedImagenes) before any of the fetchedImagenes.push(fetchedImagen) has been called, so you're setting an empty array.
The quick fix is to set the array to the state whenever a download URL is determined by moving it into the then callback:
firebase.storage().ref().child('PR/Gallery').listAll().then(function (result) {
result.items.forEach((itemRef) => {
itemRef.getDownloadURL().then((link) => {
const fetchedImagen = link
fetchedImagenes.push(fetchedImagen)
setImagenes(fetchedImagenes)
})
});
})
This will work, but may result in some flicker as you're updating the UI whenever any download URL is determined.
If you want to only update the state/UI once, you're looking for Promise.all and it'll be something like:
firebase.storage().ref().child('PR/Gallery').listAll().then(function (result) {
const promises = result.items.map((itemRef) => itemRef.getDownloadURL());
Promise.all(promises).then((urls) =>
setImagenes(urls)
});
})

How to update images while I change the page?

I have displayed some objects which contains pictures in it. When I try to change the page the written data like the name for example updates correctly on the other hand the picture stays the same
I tried placing an imageHash into the url so it updates the state.
state =
{
imageHash = Date.now()
}
return (
<div>
{mediaId.media && mediaId.media.map(photo => (
<img src={`http://127.0.0.1:8000/api/media/${photo.id}?${imageHash}`} alt={`media${photo.id}`}/>
))}
</div>
);
I need the corresponding photo to show.
I found the solution on my own.
UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.id !== this.props.id) {
this.setState({
id: nextProps.id,
imageHash: nextProps.imageHash
});
}
setImmediate(() => this.loadData());
}
It checks for props changes and if there are any it immediately loads the data with the new props.

MapMarker does not update description onPress immediately

I am trying to learn how to use React Native maps and I am trying to add in custom Map Markers. For some reason, when I try to use the following code, the image updates properly but the description does not update properly until the second click. The first click will show "not selected" but clicking on the same marker will show the actual text I want. How can I fix this?
Since the image is updating to the newImage, I know
this.state.selectedMarkerIndex === i
but the same equality does not apply to description for some reason?
state = {busText:[]}
fetchData=(i, index)=>{
fetch('LINK TO GET BUSES'+ i.toString() + '/buses', {method:'GET'})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
selectedMarkerIndex: index,
busText: responseJson
},
()=>{
console.log("selected index: " + this.state.selectedMarkerIndex)
}
)
console.log(JSON.stringify(this.state.busText));
console.log("_______________________________________________________");
})
}
renderMarkers = ()=>{
return busStops.stops.map((stop, i) => {
return <Marker marker
key={ `${i}` }
coordinate={{latitude: stop.location.latitude, longitude: stop.location.longitude}}
title = {stop.stopName}
image = {this.state.selectedMarkerIndex === i ? newImage : busStopImage}
description={this.state.selectedMarkerIndex === i ? JSON.stringify(this.state.busText) : "not selected"}
onPress={() => {
this.fetchData(stop.stopID, i)
console.log(this.state.selectedMarkerIndex + "i :" + i)
}
}
/>
})
}
I expect the description of the MapMarker to be updated when I click on it with what is fetched but that is not occurring.
A couple of things: To guarantee execution after setState you'll need to put your
this.setState({busText: responseJson})
in the fetchData() callback. Even better, set busText state earlier, where you're setting selectedMarkerIndex state.
Also for what it's worth, if you're having response time issues, try dropping some of your console.log() calls. Native (especially iOS) gets bogged down by them.

Resources