React-How to display make objects loop in react - javascript

Here is what i tried
episode.js
import Parser from "rss-parser";
import React from "react";
export default function Episode() {
const parser = new Parser();
const url1 = "https://anchor.fm/s/75abc654/podcast/rss";
const [data, setData] = React.useState({});
(async () => {
let data = await parser.parseURL(url1);
setData(data);
// console.log(data.title)
// data.items.forEach((item) => {
// console.log(item.title)
//console.log(item.pubDate.slice(5, 17))
//console.log(item.enclosure.url)
// console.log(item.itunes.image)
});
})();
return(
<h1>{item.title}</h1>
{data.items.map((item, index)=>{
return(
<h1>{item.title}</h1>
)})}
)
}
And the output is blank screen.. No error in console.. Help me to get the data from the rss feed without blank screen

You're calling async method unlimited time! You need to call it once via useEffect just when component rendered for first time:
import Parser from "rss-parser";
import React, { useEffect } from "react";
function Episode() {
const parser = new Parser();
const url1 = "https://anchor.fm/s/75abc654/podcast/rss";
const [data, setData] = React.useState({});
useEffect(() => {
(async () => {
let data = await parser.parseURL(url1);
console.log(data);
setData(data);
})();
}, []);
return (
<>
{data.items?.map((item, index) => (
<h1>{item.title}</h1>
))}
</>
);
}
export default function App() {
return <Episode />;
}

Just replace your async function with a useEffect hook like this
useEffect(() => {
async function fetchMyAPI() {
let data = await parser.parseURL(url1);
setData(data);
// console.log(data.title)
// data.items.forEach((item) => {
// console.log(item.title)
//console.log(item.pubDate.slice(5, 17))
//console.log(item.enclosure.url)
// console.log(item.itunes.image)
}
fetchMyAPI();
}, []);
This will be executed once every time when your component is loaded on screen
Also change the data.item.map to
{data.items?.map((item, index) => {
return <h1>{item.title}</h1>;
})}
Else it will throw error on first render

Related

Passing arguments to Custom Hook onClick

I have a simple react app in which I am fetching the data using jsonplaceholder API and displaying the data with a delete button. I have a function deleteUser inside the User.js component. Now I want to make this deleteUser function a general function so I created a separate hook for it.
Now I want to pass arguments to that custom hook but I get the error
React Hooks must be called in a React function component or a custom
React Hook function react-hooks/rules-of-hooks
userDelete.js
import { useFetch } from "./useFetch";
export const useDelete = (userName) => {
const { data, setData} = useFetch();
const newData = data.filter((dataItem) => dataItem.name !== userName);
console.log(newData);
setData(newData)
};
useFetch.js
import { useState, useEffect } from "react";
export const useFetch = () => {
const [loading, setLoading] = useState(false);
const [data, setData] = useState([]);
const url = `https://jsonplaceholder.typicode.com/users`;
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url);
const data = await response.json();
console.log(data);
setData(data);
setLoading(false);
return;
} catch (error) {
console.log("Error", error);
}
};
useEffect(() => {
fetchData();
}, []);
return { loading, data, setData };
};
User.js
import { useFetch } from "../Hooks/useFetch";
import { useDelete } from "../Hooks/useDelete";
const Users = () => {
const { loading, data, setData } = useFetch();
const deleteCallback = useDelete(data);
const deleteUser = (userName) => {
const newData = data.filter((dataItem) => dataItem.name !== userName);
console.log("newData", newData);
setData(newData);
};
return (
<>
<h1>Custom Hook Example</h1>
{loading && <h4>Fetching Data...</h4>}
{data.map((data, index) => (
<div
key={index}
style={{
border: "2px solid red",
width: "fit-content",
margin: "0 auto"
}}
>
<p>Name: {data.name}</p>
<article>Email: {data.email}</article>
{/* <button onClick={(e) => deleteUser(data.name, e)}>Delete</button> */}
<button onClick={() => useDelete(data.name)}>Delete</button>
</div>
))}
{data.length === 0 && (
<>
<p>No Items to Show</p>
</>
)}
</>
);
};
export default Users;
What am I doing wrong ?

How to avoid unnecessary API calls with useEffect?

I'm still beginner to ReactJS and I'm having trouble rendering a list.
I don't know why, all the time calls are being made to my API. Since I don't put any dependency on useEffect, that is, I should only render my function once.
I don't understand why this is happening. Can you tell me what I'm doing wrong?
Here's my code I put into codesandbox.io
import React from "react";
import axios from "axios";
import "./styles.css";
const App = () => {
const BASE_URL = "https://pokeapi.co/api/v2";
const [pokemons, setPokemons] = React.useState([]);
const getAllPokemons = async () => {
const { data } = await axios.get(`${BASE_URL}/pokemon`);
data.results.map((pokemon) => getPokeType(pokemon));
};
const getPokeType = async (pokemon) => {
const { data } = await axios.get(pokemon.url);
setPokemons((prev) => [...prev, data]);
};
React.useEffect(() => {
getAllPokemons();
}, []);
console.log(pokemons);
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
{pokemons.map((pokemon) => (
<p key={pokemon.id} style={{ color: "blue" }}>
{pokemon.name}
</p>
))}
</div>
);
};
export default App;
Thank you very much in advance.
Your issue is that you are calling setPokemons inside getPokeType (which is called for each data in part). Your useEffect is called just once (as expected) and the ${BASE_URL}/pokemon call is executed just once too. But getPokeType is called 20 times and the pokemons state is changed 20 times as well (once for each instance from data.results).
What I would recommend in your case (instead of what you have now) is:
Create a list of all the pokemons and
Set the state just once at the end.
So something like:
...
const getPokeType = async (pokemon) => {
const { data } = await axios.get(pokemon.url);
return data;
};
const getAllPokemons = async () => {
const { data } = await axios.get(`${BASE_URL}/pokemon`);
const pokemons = await Promise.all(
data.results.map((pokemon) => getPokeType(pokemon))
);
setPokemons(pokemons);
};
React.useEffect(() => {
getAllPokemons();
}, []);
...
I was just having the same issue in my project the way I solved is by moving the function definition inside the useEffect
React.useEffect(() => {
const getAllPokemons = async () => {
const { data } = await axios.get(`${BASE_URL}/pokemon`);
data.results.map((pokemon) => getPokeType(pokemon));
};
getAllPokemons();
}, []);
If this solves your problem please accept the answer.

Why can't I render multiple cards using map?

I'm trying to render multiple cards by pulling data from the API. But the return is an array, I don't understand why the map is not working.
const CharacterCard = () => {
const [showModal, setShowModal] = useState(false)
const openModal = () => {
setShowModal(prev => !prev)
}
const characters = useRequestData([], `${BASE_URL}/characters`)
const renderCard = characters.map((character) => {
return (
<CardContainer key={character._id} imageUrl={character.imageUrl}/>
)
})
return (
<Container>
{renderCard}
<ModalScreen showModal={showModal} setShowModal={setShowModal} />
</Container>
)
}
export default CharacterCard
The hook is this
import { useEffect, useState } from "react"
import axios from "axios"
const useRequestData = (initialState, url) => {
const [data, setData] = useState(initialState)
useEffect(() => {
axios.get(url)
.then((res) => {
setData(res.data)
})
.catch((err) => {
console.log(err.data)
})
}, [url])
return (data)
}
export default useRequestData
console error image
requisition return image
API: https://disneyapi.dev/docs
Looks like the default value of the characters is undefined.
So something like (characters || []).map.. will help I think.
For deeper look at this you can debug useRequestData hook, as I can't see the source of that hook from you example

logging the data but not rendering p tag , why?

I am using firebase firestore and i fetched the data , everything is working fine but when i am passing it to some component only one item gets passed but log shows all the elements correctly.
I have just started learning react , any help is appreciated.
import React, { useEffect, useState } from 'react'
import { auth, provider, db } from './firebase';
import DataCard from './DataCard'
function Explore() {
const [equipmentList, setEquipments] = useState([]);
const fetchData = async () => {
const res = db.collection('Available');
const data = await res.get();
data.docs.forEach(item => {
setEquipments([...equipmentList, item.data()]);
})
}
useEffect(() => {
fetchData();
}, [])
equipmentList.forEach(item => {
//console.log(item.description);
})
const dataJSX =
<>
{
equipmentList.map(eq => (
<div key={eq.uid}>
{console.log(eq.equipment)}
<p>{eq.equipment}</p>
</div>
))
}
</>
return (
<>
{dataJSX}
</>
)
}
export default Explore
You have problems with setting fetched data into the state.
You need to call setEquipments once when data is prepared because you always erase it with an initial array plus an item from forEach.
The right code for setting equipment is
const fetchData = async () => {
const res = db.collection('Available');
const data = await res.get();
setEquipments(data.docs.map(item => item.data()))
}

how to get updated data automatically after 10 sec using setinterval

i am trying to get data after each 10 seconds, i did it perfectly but the problem is my DOM renders first time i get data but as 10 seconds passed it did'nt update data and shows an error related to data...
here's the DOM error
CODE
App.js
import { Appbar } from './components/pageOne/Appbar'
import { Cards } from './components/pageOne/Cards'
import { fetchData } from './components/FetchDataFromApi'
function App() {
const [data, setData] = useState({})
const a = useEffect(() => {
let interval = setInterval(() => setData(), 10000)
return () => clearInterval(interval)
})
useEffect(() => {
(async () => {
const fetchedData = await fetchData();
setData(fetchedData)
})()
// let interval = setInterval(() => setData(), 10000)
// return () => clearInterval(interval)
}, [a])
return (
<>
<Appbar />
<Cards data = {data} />
</>
)
}
export default App;
index.js
const url = 'https://covid19.mathdro.id/api'
export const fetchData = async (country) => {
let changeableUrl = url
if (country) {
changeableUrl = `${url}/countries/${country}`
}
try {
const {data: {confirmed, recovered, deaths}} = await axios.get(changeableUrl)
return { confirmed,
recovered,
deaths
}
}
catch
(error) {
return error
}
}```
You're setting the data to undefined after 10 seconds -
let interval = setInterval(() => setData(), 10000)
You need to go and fetch the data again -
let interval = setInterval(async () => {
const fetchedData = await fetchData();
setData(fetchedData)
}, 10000);
destructing in fetchData function is not correct.
export const fetchData = async (country) => {
let changeableUrl = url
if (country) {
changeableUrl = `${url}/countries/${country}`
}
try {
const resp = await axios.get(changeableUrl);
const { confirmed, recovered, deaths } = resp.data;
return { confirmed,
recovered,
deaths
}
}
catch
(error) {
return error
}
}
useEffect is not used correctly. Here is the correction.
import { Appbar } from "./components/pageOne/Appbar";
import { Cards } from "./components/pageOne/Cards";
import { fetchData } from "./components/FetchDataFromApi";
function App() {
const [data, setData] = useState({});
useEffect(() => {
let interval = setInterval(async () => {
const newData = await fetchData();
setData(newData);
}, 10000);
return () => clearInterval(interval);
}, []);
return (
<>
<Appbar />
<Cards data={data} />
</>
);
}
export default App;
You can also checkout this sample code.
https://codesandbox.io/s/festive-lewin-vl9g0?file=/src/App.js

Categories

Resources