`
import React, { useState, useEffect } from "react";
const BlogSidebar = () => {
const [sliders, setSliders] = useState([]);
useEffect(() => {
const fetchData = async () => {
const response = await fetch(
"https://scm.vipstendo.com/AdminService/api/Slider/GetSliders?LangCode=tr"
);
const data = await response.json();
setSliders(data);
};
fetchData();
}, []);
return (
<div>
{sliders.map((slider) => (
<div
key={slider.Ref}
className="block-finder__image"
style={{ backgroundImage: `url(${`https://scm.vipstendo.com/AdminService/${slider.ImageLocation}`})` }}></div>
))}
</div>
);
};
export default BlogSidebar;
"IsImage":false,
"ImageLocation":"SliderImages/4e82761f-20a6-4ade-9da3-5d97aa3355d8.mp4",
"IsImage":true,
"ImageLocation":"SliderImages/65f91723-9947-4e31-a316-fa728bb5c128.jpg"
"IsImage":true,
"ImageLocation":"SliderImages/4ee27e68-74e3-45cf-a16d-39c2f607f932.jpg"`
Related
I'm trying to play with the Star Wars API and set Infinite Scroll, but I can't handle adding more pages. I'm displaying the first page.
I know I'm doing something wrong in the getMorePeople function, but I have no idea how to change it. Could someone suggest something?
import {useEffect, useState} from "react";
import axios from "axios";
const swapi = axios.create({
baseURL: "https://swapi.dev/api/"
});
const InfiniteScroll = () => {
const [people, setPeople] = useState([]);
const [page, setPage] = useState(1);
const peopleApi = swapi.get(`people/?page=${page}`);
const fetchPeople = async () => {
const response = await peopleApi;
const transformPeople = response.data.results.map(PeopleObject => {
return {
name: PeopleObject.name,
height: PeopleObject.height,
hair_color: PeopleObject.hair_color,
skin_color: PeopleObject.skin_color,
birth_year: PeopleObject.birth_year
}
})
setPeople(transformPeople);
}
useEffect(() => {
fetchPeople();
}, []);
const getMorePeople = async (page, people = []) => {
const {next, results} = await fetchPeople(people);
people = [...people, ...results];
if (next !== null) {
return getMorePeople(next, people);
}
return people;
}
return (
<>
<div>
{people.map((onePerson) => {
return (
<div key={onePerson.name}>
<p: {onePerson.name}</p>
<p>Height: {onePerson.height}</p>
<p>Hair color: {onePerson.hair_color}</p>
<p>Skin color: {onePerson.skin_color}</p>
<p>Birth year: {onePerson.birth_year}</p>
</div>
)
})}
<button onClick={getMorePeople}>Next</button>
</div>
</>
)
};
export default InfiniteScroll;
Check if this suits your needs:
import { useEffect, useState } from "react";
import axios from "axios";
const swapi = axios.create({
baseURL: "https://swapi.dev/api/"
});
const InfiniteScroll = () => {
const [people, setPeople] = useState([]);
const [page, setPage] = useState(1);
const fetchPeople = async (page = 1) => {
const response = await swapi.get(`people/?page=${page}`);;
const transformPeople = response.data.results.map(PeopleObject => {
return {
name: PeopleObject.name,
height: PeopleObject.height,
hair_color: PeopleObject.hair_color,
skin_color: PeopleObject.skin_color,
birth_year: PeopleObject.birth_year
}
})
setPeople([...people, ...transformPeople]); //append the new page into the existing array
}
useEffect(() => {
fetchPeople();
}, []);
const getMorePeople = async () => {
const nextPage = page + 1;
setPage(nextPage);
fetchPeople(nextPage);
}
return (
<>
<div>
{people.map((onePerson) => {
return (
<div key={onePerson.name}>
<p> {onePerson.name}</p>
<p>Height: {onePerson.height}</p>
<p>Hair color: {onePerson.hair_color}</p>
<p>Skin color: {onePerson.skin_color}</p>
<p>Birth year: {onePerson.birth_year}</p>
<br />
</div>
)
})}
<button onClick={getMorePeople}>Next</button>
</div>
</>
)
};
export default InfiniteScroll;
import { useState, useEffect } from 'react';
import axios from 'axios'
import { Loading } from './loading';
function News({ pageSize }) {
const [isLoading, setIsLoading] = useState(false)
const [state, setState] = useState({
article: [],
page: 1
}
)
const getUsers = async () => {
setIsLoading(true)
let res = await axios.get(`https://newsapi.org/v2/everything?domains=wsj.com&apiKey=79b02b430c1946cd9c505d3f91d7aec6&page=1&pageSize=${pageSize}`);
setState({article: res.data.articles})
setIsLoading(false)
};
useEffect(() => {
getUsers()
}, [])
const handleNext = async () => {
setIsLoading(true)
let res = await axios.get(`https://newsapi.org/v2/everything?domains=wsj.com&apiKey=79b02b430c1946cd9c505d3f91d7aec6&page=${state.page + 1}&pageSize=${pageSize}`);
setState({article: res.data.articles, page: state.page + 1})
setIsLoading(false)
}
let data = Array.from(state.article)
return (
<div>
<h2>News</h2>
<button onClick={handleNext}>Next</button>
{isLoading && <Loading />}
{!isLoading && data.map((elements) => {
return (
<div key={elements.url} style={{ marginBottom: '2rem' }}>
<div> {elements.description} </div>
<div>{new Date(elements.publishedAt).toGMTString()}</div>
</div>
)
})}
</div>
);
}
export default News;
When I take states separately for data and page, I'm able to display next page's data. But now that I've created one state to manage multiple objects, it displays back first page's data instead of next page's data. I don't know what I'm doing wrong. Pls help me!
Ignore the redundancy.
Try this:
const getUsers = async () => {
setIsLoading(true)
let res = await axios.get(`https://newsapi.org/v2/everything?domains=wsj.com&apiKey=79b02b430c1946cd9c505d3f91d7aec6&page=1&pageSize=${pageSize}`);
setState({...state, article: res.data.articles})
setIsLoading(false)
};
I am trying to setup infinite scrolling using React Hooks, I am getting the data correctly from the node backend (3 dataset per request), and when I scroll new data is also added correctly in the array (in the loadedPlaces state), but the page is going back to top on re render, I need to prevent this behavior. How do I prevent this, and below is my code
import React, { useEffect, useState } from "react";
import "./App.css";
function App() {
const [page, setPage] = useState(1);
const [loadedPlaces, setLoadedPlaces] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const getPlaces = async () => {
try {
setIsLoading(true);
const url = `http://localhost:5000/api/places/user/${id}?page=${page}&size=3`;
const responseData = await fetch(url);
const data = await responseData.json();
console.log(data);
setLoadedPlaces((prev) => [...prev, ...data.places]);
setIsLoading(false);
} catch (error) {}
};
getPlaces();
}, [page]);
window.onscroll = function (e) {
if (
window.innerHeight + document.documentElement.scrollTop ===
document.documentElement.offsetHeight
) {
setPage(page + 1);
}
};
return (
<div className='App'>
<h1>Infinite Scroll</h1>
{!isLoading &&
loadedPlaces.length > 0 &&
loadedPlaces.map((place, index) => (
<div key={index} className={"container"}>
<h1>{place.location.lat}</h1>
<h1>{place.location.lng}</h1>
<h1>{place.title}</h1>
<h1>{place.description}</h1>
<h1>{place.address}</h1>
<hr></hr>
</div>
))}
</div>
);
}
export default App;
Any help is highly appreciated
This is happening because whenever you scroll you are calling
window.onscroll = function (e) {
if (
window.innerHeight + document.documentElement.scrollTop ===
document.documentElement.offsetHeight
) {
setPage(page + 1);
}
};
And it's changing the page count and that changed page count leads to again run the
useEffect(() => {
const getPlaces = async () => {
try {
setIsLoading(true);
const url = `http://localhost:5000/api/places/user/${id}?page=${page}&size=3`;
const responseData = await fetch(url);
const data = await responseData.json();
console.log(data);
setLoadedPlaces((prev) => [...prev, ...data.places]);
setIsLoading(false);
} catch (error) {}
};
getPlaces();
}, [page]);
and in that function, you are doing setIsLoading(true) so that it is again rendering this because of
{!isLoading && <-----
loadedPlaces.length > 0 &&
loadedPlaces.map((place, index) => (
<div key={index} className={"container"}>
<h1>{place.location.lat}</h1>
<h1>{place.location.lng}</h1>
<h1>{place.title}</h1>
<h1>{place.description}</h1>
<h1>{place.address}</h1>
<hr></hr>
</div>
))}
And that leads you to the top of the page
You can try this approach:
import React, { useEffect, useState } from "react";
import "./App.css";
function App() {
const [page, setPage] = useState(1);
const [loadedPlaces, setLoadedPlaces] = useState([]);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const getPlaces = async () => {
try {
setIsLoading(true);
const url = `http://localhost:5000/api/places/user/${id}?page=${page}&size=3`;
const responseData = await fetch(url);
const data = await responseData.json();
console.log(data);
setLoadedPlaces((prev) => [...prev, ...data.places]);
setIsLoading(false);
} catch (error) {}
};
getPlaces();
}, [page]);
window.onscroll = function (e) {
if (
window.innerHeight + document.documentElement.scrollTop ===
document.documentElement.offsetHeight
) {
setPage(page + 1);
}
};
return (
<div className='App'>
<h1>Infinite Scroll</h1>
{
loadedPlaces.length > 0 &&
loadedPlaces.map((place, index) => (
<div key={index} className={"container"}>
<h1>{place.location.lat}</h1>
<h1>{place.location.lng}</h1>
<h1>{place.title}</h1>
<h1>{place.description}</h1>
<h1>{place.address}</h1>
<hr></hr>
</div>
))}
</div>
);
}
export default App;
You can add this.
function ScrollToBottom(){
const elementRef = useRef();
useEffect(() => elementRef.current.scrollIntoView());
return <div ref={elementRef} />;
};
And then:
return (
<div className='App'>
<h1>Infinite Scroll</h1>
{!isLoading &&
loadedPlaces.length > 0 &&
loadedPlaces.map((place, index) => (
<div key={index} className={"container"}>
<h1>{place.location.lat}</h1>
<h1>{place.location.lng}</h1>
<h1>{place.title}</h1>
<h1>{place.description}</h1>
<h1>{place.address}</h1>
<hr></hr>
</div>
))}
<ScrollToBottom />
</div>
);
I want to put an incoming API to the status but it says undefined.
I want to discard my data coming to randomcocktail and then use it.
Random.tsx
import { useState, useEffect } from "react";
import { CocktailType } from "../Utils/data";
import "../Style/index.scss";
const Random = () => {
const [randomCocktail, setRandomCocktail] = useState<CocktailType[]>();
useEffect(() => {
const getRand = async () => {
const response = await fetch(
"https://www.thecocktaildb.com/api/json/v1/1/random.php"
);
const data = await response.json();
const { cocktail = [] } = data;
setRandomCocktail(cocktail[0]);
console.log(data);
console.log(randomCocktail);
};
getRand();
}, []);
return (
<div className="randomPage">
<div className="leftRand"></div>
<div className="rightRand"></div>
</div>
);
};
export default Random;
data.ts
export type CocktailType={
strDrink :string;
strTag:string|null;
strVideo:string|null;
strCategory:string;
strIBA:string|null;
strAlcoholic:string;
strGlass:string;
strInstructions:string;
strDrinkThumb:string;
}
api : https://www.thecocktaildb.com/api/json/v1/1/random.php
Try this
import { useState, useEffect } from "react";
import { CocktailType } from "../Utils/data";
import "../Style/index.scss";
const Random = () => {
const [randomCocktail, setRandomCocktail] = useState<CocktailType[]>();
useEffect(() => {
const getRand = async () => {
const response = await fetch(
"https://www.thecocktaildb.com/api/json/v1/1/random.php"
);
const data = await response.json();
const cocktail = data.drinks;
setRandomCocktail(cocktail[0]);
console.log(data);
console.log(randomCocktail);
};
getRand();
}, []);
return (
<div className="randomPage">
<div className="leftRand"></div>
<div className="rightRand"></div>
</div>
);
};
export default Random;
I'm trying to take out the fetchImages function from the following component and put it inside a new component:
import React, { useState, useEffect } from 'react';
import axios from 'axios';
import UnsplashImage from './UnsplashImage';
const Collage = () => {
const [images, setImages] = useState([]);
const [loaded, setIsLoaded] = useState(false);
const fetchImages = (count = 10) => {
const apiRoot = 'https://api.unsplash.com';
const accessKey =
'<API KEY>';
axios
.get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
.then(res => {
console.log(res);
setImages([...images, ...res.data]);
setIsLoaded(true);
});
};
useEffect(() => {
fetchImages();
}, []);
return (
<div className="image-grid">
{loaded
? images.map(image => (
<UnsplashImage
url={image.urls.regular}
key={image.id}
alt={image.description}
/>
))
: ''}
</div>
);
};
export default Collage;
For this, I created a new component called api.js, removed the entire fetchImage function from the above component and put it in to api.js like this:
api.js
const fetchImages = (count = 10) => {
const apiRoot = 'https://api.unsplash.com';
const accessKey =
'<API KEY>';
axios
.get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
.then(res => {
console.log(res);
setImages([...images, ...res.data]);
setIsLoaded(true);
});
};
export default fetchImages;
Next I took setIsLoaded(true); from api.js and paste it inside Collage component like this:
useEffect(() => {
fetchImages();
setIsLoaded(true);
}, []);
Now I can import fetchImages in to Collage component.
However, I don't know what should I do with this line inside the fetchImages function? This needs to go to Collage component, but res.data is not defined inside Collage component.
setImages([...images, ...res.data]);
How should I handle it?
There is many way to do that, but in your case.
You should use
const fetchImages = (afterComplete, count = 10) => {
const apiRoot = 'https://api.unsplash.com';
const accessKey = '<API KEY>';
axios
.get(`${apiRoot}/photos/random?client_id=${accessKey}&count=${count}`)
.then(res => {
console.log(res);
afterComplete(res.data);
});
};
export default fetchImages;
And in your Collage component:
const afterComplete = (resData) =>{
setImages([...images, ...resData]);
setIsLoaded(true);
}
useEffect(() => {
fetchImages(afterComplete);
}, []);
What you can do is create a custom hook ( sort of like a HOC)... Since I don't have an unsplash API key I'll give you an example with a different API but the idea is the same:
Here is your custom hook:
import { useState, useEffect } from 'react';
export const useFetch = url => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const fetchUser = async () => {
const response = await fetch(url);
const data = await response.json();
const [user] = data.results;
setData(user);
setLoading(false);
};
useEffect(() => {
fetchUser();
}, []);
return { data, loading };
};
Here is how you can use it in your component:
import { useFetch } from './api';
const App = () => {
const { data, loading } = useFetch('https://api.randomuser.me/');
return (
<div className="App">
{loading ? (
<div>Loading...</div>
) : (
<>
<div className="name">
{data.name.first} {data.name.last}
</div>
<img className="cropper" src={data.picture.large} alt="avatar" />
</>
)}
</div>
);
};
Here is a live demo: https://codesandbox.io/s/3ymnlq59xm