FetchAPI GraphQL / Gatsby throw error on frontend if null data - reactjs

I have set up a band site using Gatsby which utilises the Bandsintown API to get events whether they are upcoming or past events.
Displaying past events is fine, but I would like to display a message on the frontend if there are no upcoming events / no events i.e no data comes back from the fetch API call. I am not really sure how to go about this?
Currently I cannot even build the solution and get error in my console:
Cannot query field "allBandsInTownEvent" on type "Query"
Can anybody point me in the right direction?
gatsby-node.js (local plugin)
const fetch = require("node-fetch")
const queryString = require("query-string")
exports.sourceNodes = (
{ actions, createNodeId, createContentDigest },
configOptions
) => {
const { createNode } = actions
delete configOptions.plugins
const processEvent = event => {
const nodeId = createNodeId(`bandsintown-event-${event.id}`)
const nodeContent = JSON.stringify(event)
const nodeData = Object.assign({}, event, {
id: nodeId,
parent: null,
children: [],
internal: {
type: `BandsInTownEvent`,
content: nodeContent,
contentDigest: createContentDigest(event),
},
})
return nodeData
}
const artist = configOptions.artist
const app_id = configOptions.app_id
const apiUrl = `https://rest.bandsintown.com/artists/${artist}/events?app_id=${app_id}&date=upcoming` //upcoming or past
return fetch(apiUrl).then(response =>
response.json().then(data => {
if (Object.entries(data).length === 0) {
return some kind of error? i.e document.querySelector(".no-shows").innerHTML = "No Shows on at the moment"
}
data.forEach(event => {
const nodeData = processEvent(event)
createNode(nodeData)
})
})
)
}
events.js
import React from "react"
import { graphql, StaticQuery } from "gatsby"
import "./index.scss"
export default () => (
<StaticQuery
query={graphql`
query EventsQuery {
allBandsInTownEvent(
limit: 8
sort: { fields: [datetime], order: DESC }
) {
nodes {
id
venue {
city
country
name
}
artist {
id
facebook_page_url
image_url
name
}
datetime(formatString: "ddd, MMM DD YYYY")
url
}
}
}
`}
render={data => (
<div className="Events">
<div className="event-header">Tour Dates</div>
<div className="event-content">
{data.allBandsInTownEvent.nodes.map(node => (
<div className="event-item" key={node.id}>
<div className="event-details">
<div className="event-datetime">{node.datetime}</div>
<div className="event-name">{node.venue.name}</div>
<div className="event-venue">
<div className="city">{node.venue.city}</div>
<div className="region">{node.venue.region}</div>
<div className="country">{node.venue.country}</div>
</div>
</div>
<div className="event-cta">
<a
href={node.url}
rel="noreferrer"
target="_blank"
title={node.title}
>
Tickets
</a>
</div>
</div>
)
)}
</div>
</div>
)}
/>
)

Related

Fetching and rendering a component in a loop

I have a string array that contains usernames. I want to fetch those users in a loop, put them in an array and render a component for each user. I can retrieve the data from API and print it on console but the code below gives me a white screen.
Here I'm trying to fetch data one by one using fav_list array than contains usernames. Then I want to send the data to another component called InfluencerFavoritesCard and render them. Where I'm doing wrong?
import React from 'react'
import InfluencerFavoritesCard from '../components/influencerFavoritesCard/InfluencerFavoritesCard';
import "./indexPages.css"
import "./favorites.css"
const fav_list = ["cagritaner", "acunilicali", "neslihanatagul"];
async function ListFavorites() {
let array = new Array;
var fetches = [];
for (let i = 0; i < fav_list.length; i++) {
console.log(fav_list[i]);
let uname = fav_list[i];
fetches.push(
fetch(`http://localhost:3001/api/users/${uname}`)
.then(res => {return res.text(); })
.then(res => {
array.push(res);
console.log(res);
}
)
);
}
Promise.all(fetches).then(function () {
console.log(fetches);
console.log(array[0]);
console.log(array.length);
});
return (
<div>
{array.map(item => (< InfluencerFavoritesCard infCard = { item } /> ))}
</div>
);
}
function Favorites() {
return (
<div className='favoritesMain'>
<div className='favoritesTitle-div'>
<h3 className="favoritesTitle">FAVORİLER</h3>
</div>
<div className='favoritesContainer-wrapper'>
<div className='favoritesContainer'>
{<ListFavorites/>}
</div>
</div>
<div className='favoritesFooter'></div>
</div>
);
}
export default Favorites
InfluencerFavoritesCard.jsx
import React from 'react';
import './influencerFavoritesCard.css';
const InfluencerFavoritesCard = ({ infCard }) => {
return (
<div className='infCard'>
<div className='infCard-text-info' >
<div className='infCard-name'>
<h3>{infCard.name}</h3>
</div>
<div className='infCard-username'>
<h4>{infCard.username}</h4>
</div>
<div className='infCard-categories'>
<h4>{infCard.categories}</h4>
</div>
</div>
</div>
)
}
export default InfluencerFavoritesCard;
================================
UPDATED:
I have updated the parent component like below.
export function Favorites() {
const [users, setUsers] = useState([]);
const fav_list = ["cagritaner", "acunilicali", "neslihanatagul"];
useEffect(() => {
const tempUsersCollection = [];
fav_list.map((x, i) => {
fetch(`http://localhost:3001/api/users/${x}`)
.then(res => {return res.json(); })
.then(res => {
tempUsersCollection.push(res.data.tour);
console.log(res);
}
);
});
console.log(tempUsersCollection);
setUsers(tempUsersCollection);
}, []);
return (
<div className='favoritesMain'>
<div className='favoritesTitle-div'>
<h3 className="favoritesTitle">FAVORİLER</h3>
</div>
<div className='favoritesContainer-wrapper'>
<div className='favoritesContainer'>
{users.map((item, index) => (
<InfluencerFavoritesCard
infCard={item}
key={`influencer-${item.username}-${index}`}
/>
))}
</div>
</div>
<div className='favoritesFooter'></div>
</div>
);
}
output of the console.log(tempUsersCollection) (AFTER res.json() !! )
Array []
​
0: Object { username: "neslihanatagul", biography: "contact#neslihanatagul.com", profile_picture_url: "https://scontent.fist4-1.fna.fbcdn.net/v/t51.2885-15/5787050…0_AfDfN8wtsD18vya_aLLw6M4UpP8Xx16jb9b4Hsh6cJ3wjA&oe=63A713AF", … }
​
1: Object { username: "cagritaner", biography: "Hüzünlü Bir Ponçik ve Erkeklerin İç Sesi kitaplarının yazarı.\niş birlikleri için; #goygoynetworkinfo", profile_picture_url: "https://scontent.fist4-1.fna.fbcdn.net/v/t51.2885-15/4424442…0_AfCXmyBbUrKQjpzsGEHNEMHXoNP7HZ8UKaYXHAL4S0DFlA&oe=63A6926B", … }
​
2: Object { username: "acunilicali", biography: "Acun Ilıcalı Resmi Instagram Hesabıdır.", profile_picture_url: "https://scontent.fist4-1.fna.fbcdn.net/v/t51.2885-15/1193932…0_AfDuL0toVKsSGOrnXWISBMAR78G79QwNfxJmm5cNFBuW2A&oe=63A78969", … }
​
length: 3
​
<prototype>: Array []
Favorites.jsx:136
The thing is that return statement is being rendered before all the promises are resolved, meaning that it's empty. This is exactly how it should work, so no bug here.
What you need to do is as other mentioned, use useState and useEffect to control the data:
// This will hold your collection
const [users, setUsers] = useState([])
...
// And here you need to update that collection
useEffect(()=>{
const temp = []
fetch(`http://localhost:3001/api/users/${uname}`)
.then(res => {return res.text(); })
.then(res => {
temp.push(res);
}
)
setUsers(temp)
}, [])
Later on the return you can do this:
// This controls if there are no users
if(users.length <= 0){
return <>There are no users</>
}
return (
<div className='favoritesMain'>
<div className='favoritesTitle-div'>
<h3 className="favoritesTitle">FAVORİLER</h3>
</div>
<div className='favoritesContainer-wrapper'>
<div className='favoritesContainer'>
{users.map(item => (<InfluencerFavoritesCard infCard = { item } /> ))}
</div>
</div>
<div className='favoritesFooter'></div>
</div>
);
Created a CodeSandbox so you can see this working
UPDATE:
// Call the function after the first render
useEffect(() => {
fetchUsers();
}, []);
// Wrapped all the calls in a Promise.all and update the state
async function fetchUsers() {
const response = await Promise.all(
fav_list.map((x) =>
fetch(`https://pokeapi.co/api/v2/pokemon/${x}`)
.then((res) => res.json())
.then((user) => user)
)
);
console.log(response);
setUsers(response);
}
// Handle the case where nothing is retrieved
if (users.length <= 0) {
return <>There are no users</>;
}
To fetch data asynchronously, you need to use the useEffect hook. You should store the data using a useState hook and then set that data when you get a response from your fetch request.

React reading data form the server

I am getting an error from strapi backend data when I fetch particular data into the front end react app I get an error when I log the data into the browser console I see my data in the browser console.
query GetPromoProducts {
allStrapiProduct(filter: {promo: {eq: true}}) {
edges {
node {
strapiId
name
variants {
images {
url
}
}
}
}
}
}
`)
const [selectedSlides, setSelectedSlides] = useState(0)
console.log(data);
var slides = [];
data.allStrapiProduct.edges.map(({node}) => {
console.log(node.variants[0].images[0]);
})
Debugging
To debug the server side, use optional chaining and console.log to work your way up to the object's that returning null.
Not sure what the exact code looks like, based on question.
const myQuery = graphql`
query GetPromoProducts {
allStrapiProduct(filter: { promo: { eq: true } }) {
edges {
node {
strapiId
name
variants {
images {
url
}
}
}
}
}
}
`;
const Component = () => {
const [selectedSlides, setSelectedSlides] = useState(0);
console.log(data);
data.allStrapiProduct.edges.map(({ node }) => {
// For this case, use optional chaining to work your way up the tree
console.log(node);
console.log(node?.variants);
console.log(node?.variants?.[0]);
console.log(node?.variants?.[0]?.images);
console.log(node?.variants?.[0]?.images?.[0]);
});
};
To stop right at the area this happens:
data.allStrapiProduct.edges.map(({ node }) => {
if (!node?.variants?.[0]?.images?.length) {
console.log(node);
console.log(node?.variants);
console.log(node?.variants?.[0]);
console.log(node?.variants?.[0]?.images);
console.log(node?.variants?.[0]?.images?.[0]);
throw "Required data missing";
}
});
Resilient React with GraphQL
GraphQL structured data may be typed, but unless the fields are required, you have to handle null.
To make the client-side code more robust, you can use Array.prototype.filter() to skip objects with no images, or - as in this example - make components handle the case where data is missing. It's entirely up to how you want the frontend app to render it.
I haven't tested this code, so take it as "pseudo-JSX" to demonstrate handling empty graphql response fields.
const ProductVariant = ({ variant }) => {
if (!variant) return null;
return (
<div className="variant">
{variant?.images?.map?.((image, idx) => (
<img src={url} key={idx} />
))}
</div>
);
};
const ProductVariants = ({ variants }) => {
if (!variants?.length > 0) return null;
return (
<div className="variant-list">
<div>Variants</div>
<div className="variant-list--items">
{variants?.map?.((variant, idx) => (
<ProductVariant variant={variant} key={idx} />
))}
</div>
</div>
);
};
const Products = () => {
const [selectedSlides, setSelectedSlides] = useState(0);
console.log(data);
const products = data.allStrapiProduct.edges.map(({ node }) => {
// Handle as you deem fit
});
return (
<div id="products">
<p>Here is a list of products</p>
<div className="products">
{products?.map?.((product, idx) => {
return (
<div className="product" key={idx}>
{product?.variants?.length > 1 && (
<ProductVariants variants={variants} />
)}
</div>
);
})}
</div>
</div>
);
};

how to prevent multiple re-render in react

import { useSelector, useDispatch } from "react-redux";
import { useEffect, useState } from "react";
import { useHistory } from "react-router-dom";
import { IoMdArrowRoundBack } from "react-icons/io";
import axios from "axios";
import { fetchMovies } from "../../feautures/movies/moviesSlice";
import Rating from "../../components/UI/Rating/Rating";
import request from "../../requests";
import "./SingleMoviePage.scss";
import SimilarMovies from "../../components/SimilarMovies/SimilarMovies";
const SingleMoviePage = ({ match }) => {
const dispatch = useDispatch();
const [movieDetails, setMovieDetails] = useState({});
const [movieCredits, setMovieCredits] = useState({});
const history = useHistory();
console.log("single rendered")
// number month to string
const date = new Date(movieDetails.release_date);
const dateWithMonthName =
date.getFullYear() +
"-" +
date.toLocaleString("en-EN", { month: "long" }) +
"-" +
date.getDay();
/* params */
const movieId = match.params.id;
const page = match.params.page;
const genre = match.params.genre;
/* movies reducer handle */
const moviesStatus = useSelector((state) => state.movies.status);
/* base urls */
const baseImgUrl = "https://image.tmdb.org/t/p/original";
const movieDetailUrl = `https://api.themoviedb.org/3/movie/${movieId}?api_key=c057c067b76238e7a64d3ba8de37076e&language=en-US`;
const movieCastUrl = `https://api.themoviedb.org/3/movie/${movieId}/credits?api_key=c057c067b76238e7a64d3ba8de37076e&language=en-US`;
// go home page
const goHOme = () => {
history.goBack()
};
// fetch movie cast
useEffect(() => {
const fetchMovieCast = async () => {
let response = await axios.get(movieCastUrl);
response = response.data;
setMovieCredits(response);
};
fetchMovieCast();
}, [movieCastUrl]);
// fetch movie details
useEffect(() => {
const fetchMovieDetails = async () => {
let response = await axios.get(movieDetailUrl);
response = response.data;
setMovieDetails(response);
};
fetchMovieDetails();
}, [movieDetailUrl]);
let content;
if (moviesStatus === "loading") {
} else if (moviesStatus === "succeeded") {
content = (
<div
className="single-movie__container"
style={{
backgroundImage: `url(${
movieDetails.backdrop_path
? baseImgUrl + movieDetails.backdrop_path
: baseImgUrl + movieDetails.poster_path
})`,
}}
>
<div className="single-movie__details">
<IoMdArrowRoundBack
className="single-movie__back"
onClick={goHOme}
size={65}
color={"#e50914"}
/>
<h1 className="single-movie__title">{movieDetails.title}</h1>
<div className="single-movie__rate">
<Rating
rating={movieDetails.vote_average}
className="single-movie__stars"
/>
</div>
<p className="single-movie__overview">{movieDetails.overview}</p>
<div className="single-movie__informations single-movie__informations--genres">
<label className="single-movie__informations-heading">Genres</label>
<div className="single-movie__informations-container">
{movieDetails.genres?.map((genre) => {
return <div className="single-movie__info">{genre.name}</div>;
})}
</div>
</div>
<div className="single-movie__informations single-movie__informations--stars">
<label className="single-movie__informations-heading">
Starring
</label>
<div className="single-movie__informations-container">
{movieCredits.cast?.slice(0, 4).map((star) => {
return <div className="single-movie__info">{star.name}</div>;
})}
</div>
</div>
<div className="single-movie__informations single-movie__informations--released">
<label className="single-movie__informations-heading">
Release Date
</label>
<div className="single-movie__informations-container">
<div className="single-movie__info">{dateWithMonthName}</div>
</div>
</div>
<div className="single-movie__informations single-movie__informations--production">
<label className="single-movie__informations-heading">
Production
</label>
<div className="single-movie__informations-container">
{movieDetails.production_countries?.slice(0, 2).map((country) => {
return <div className="single-movie__info">{country.name}</div>;
})}
</div>
</div>
</div>
<SimilarMovies movieId={movieId} />
</div>
);
}
useEffect(() => {
if (genre === "POPULAR") {
dispatch(fetchMovies(request.fetchPopular(page)));
} else if (genre === "NOW PLAYING") {
dispatch(fetchMovies(request.fetchNowPlaying(page)));
} else if (genre === "UP COMING") {
dispatch(fetchMovies(request.fetchUpComing(page)));
}
}, [dispatch, genre, page]);
return <div className="single-movie">{content}</div>;
};
export default SingleMoviePage;
Hi all.When i clicked Card compenent it navigate me to the SingleMoviePage component.But SingleMoviePage component re-render five times.How can i find this issues's source ? And how can i prevent that ? Finally is there any problem to fetch MovieCast and MovieDetails in same useEffect hook ?
github repo : https://github.com/UmutPalabiyik/hope-movie-app
demo : https://hope-movie.web.app/page/1
The first 2 useEffect hooks fetch data separately which then update your local states, which then triggers re-rendering.
If you don't want to re-render after each data fetch (state update), I'd suggest adding a loading state. Set it to true first and return a loading icon as your content. Then after both movieDetails and movieCredits have been populated, set it to false and return the actual content. This should render twice in total.
Have you considered graphql? GraphQL can combine your api calls into one and it also handles loading state and error state.
Whatever solution you have, re-rendering will happen when you are fetching data. Initial render won't have any data and after fetching data it must re-render.
You should use only one useEffect hook your code is running for all three. React will handle the rest itself.

I am having trouble to delete individual document from my firebase firestore database

I created a react app which lists book titles and author names. The data stores in firebase firestore database and it sync with the application at frontend. The problem I am having is that to delete individual document from the collection. I'm able to access the id but unable to single out particular id to delete. I put the code below and hoping somebody can helping me out to show how I should delete individual document, at the moment it deletes all the documents. Thanks!
import React, {useState, useEffect} from 'react'
import firebase from '../config/fbConfig'
const useBooks = () => {
const [books, setBooks] = useState([])
useEffect(() => {
firebase.firestore().collection('books').onSnapshot((snapshot) => {
const newBooks = snapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}))
setBooks(newBooks)
})
},[])
return books
}
const handleOnClick = () => {
const db = firebase.firestore()
db.collection('books').get().then(snapshot => {
snapshot.docs.forEach(doc => {
const id = doc.id
db.collection('books').doc(id).delete()
console.log("Jampa thinlay Book ID:", id)
})
})
}
const BookList = () => {
const books = useBooks()
console.log('jt books', books)
return(
<div className="book_list">
<ul>
{
books.map(book =>
<li key={book.id} onClick={()=> handleOnClick()} >
<div className="title">id:{book.id}</div>
<div className="cross" > X </div>
<div className="title">book:{book.title.title}</div>
<div className="author">author: {book.author.author}</div>
</li>
)
}
</ul>
</div>
)
}
export default BookList
the problem is that in your function
const handleOnClick = () => {
const db = firebase.firestore()
db.collection('books').get().then(snapshot => {
snapshot.docs.forEach(doc => {
const id = doc.id
db.collection('books').doc(id).delete()
console.log("Jampa thinlay Book ID:", id)
})
})
}
you are looping all the documents, and are calling delete on each of them, which then your issue happens.
a solution to this would be to change the signature of your handleOnClick function to recieve the id of the item to be deleted, like so
const handleOnClick = (documentId) => {
const db = firebase.firestore();
db.collection("books").doc(documentId).delete()
.then(() => {
console.log("item with id" + documentId + "got deleted");
}).catch((e) => console.log(e));
}
the difference of the new function is that it receive the id of the document you want to delete, and deletes only that document,
and in your html you can pass the id of each book as follows
const BookList = () => {
const books = useBooks()
console.log('jt books', books)
return(
<div className="book_list">
<ul>
{
books.map(book =>
<li key={book.id} onClick={()=> handleOnClick(book.id)} > // <-----------------
<div className="title">id:{book.id}</div>
<div className="cross" > X </div>
<div className="title">book:{book.title.title}</div>
<div className="author">author: {book.author.author}</div>
</li>
)
}
</ul>
</div>
)
}

Error rendering react-redux functional component when data is deleted from firestore (useFirestoreConnect)

My ArticleList component is successfully getting & displaying the user's list of articles from firestore when I first load the app. The user can click a "Remove Article" button, which successfully removes the article from the subcollection in firestore, but it causes an error in the rendering of the react component, which seems to still be trying to render the article that was just removed and is now null. Is there something else I can do to make my react component continuously listen to the firestore data? If possible, I'd like to keep this a functional component and use hooks rather than making it a class, but I'm still learning how to use react hooks and therefore struggling a bit.
ArticleList component:
const ArticleList = (props) => {
const firestore = useFirestore();
const userId = props.auth.uid;
useFirestoreConnect([
{
collection: 'users',
doc: userId,
subcollections: [{collection: 'articles'}],
storeAs: userId + '::articles'
}
]);
const myArticles = useSelector(state => state.firestore.data[`${userId}::articles`]);
const dispatch = useDispatch();
const removeArticle = useCallback(
articleId => dispatch(removeArticleFromFirebase({ firestore }, articleId)),
[firestore]
);
if (props.auth.uid) {
return(
<div>
<h3>My Articles</h3>
<p>Currently signed in: {props.auth.email}</p>
<br/>
{myArticles ? (
Object.keys(myArticles).map(articleId => {
let article = myArticles[articleId];
let articleInformation = '';
if (articleId === props.currentPaperId) {
articleInformation =
<div>
<p>{article.year}</p>
<p>{article.description}</p>
<a target="_blank" href={article.downloadUrl}><button className='waves-effect waves-light btn-small'>See article</button></a>
<button className='waves-effect waves-light btn-small' onClick={() => {removeArticle(articleId);}}>Remove from My Articles</button>
</div>;
}
let authorName = '';
if (article.author) {
authorName = ` by ${article.author}`;
}
if (article) {
return <span key={articleId}>
<li onClick={() => {dispatch(selectArticle(articleId));}}>
<em>{article.title}</em>{authorName}
</li>{articleInformation}
</span>;
} else {
return null;
}
})
) : (
<h4>No articles yet</h4>
)
}
</div>
);
} else {
return null;
}
};
const mapStateToProps = (state) => {
return {
currentPaperId: state.currentPaperId,
auth: state.firebase.auth
};
};
export default compose(connect(mapStateToProps))(ArticleList);
And the removeArticleFromFirebase action:
export const removeArticleFromFirebase = ({ firestore }, id) => {
return (dispatch, getState) => {
const userId = getState().firebase.auth.uid;
firestore
.collection('users')
.doc(userId)
.collection('articles')
.doc(id)
.delete()
.then(() => {
console.log('Deleted article from firestore: ', id);
dispatch({ type: 'REMOVE_ARTICLE', id });
})
.catch(err => {
console.log('Error: ', err);
});
};
}
I've tried adding useState and useEffect in the ArticleList as follows (and tried having the component's return statement map through myArticlesState instead of myArticles), but no success:
const [myArticlesState, setMyArticlesState] = useState(myArticles);
useEffect(() => {
setMyArticlesState(myArticles);
}, [myArticles]);
Note: I do not currently have this article list in overall app state/redux store/props at all. This is something I was thinking of trying next, but I decided to post my question first in case I can just use hooks in this component. No other components/parts of the app need access to this particular list.
Console errors:
error image 1
error image 2
Github repo: https://github.com/jpremmel/yarp2.0
It's kind of difficult to see what's going on but it appears as though you are trying to use a property on an object that does not exist. Therefore, checking for those properties should help resolve this.
Can you try the follow code as your ArticleList?
const ArticleList = (props) => {
const firestore = useFirestore();
const userId = props.auth.uid;
useFirestoreConnect([{
collection: 'users',
doc: userId,
subcollections: [{ collection: 'articles' }],
storeAs: userId + '::articles'
}]);
const myArticles = useSelector(state => state.firestore.data[`${userId}::articles`]);
const dispatch = useDispatch();
const removeArticle = useCallback(articleId => dispatch(removeArticleFromFirebase({ firestore }, articleId)), [firestore]);
if (props.auth.uid) {
return (
<div>
<h3>My Articles</h3>
<p>Currently signed in: {props.auth.email}</p>
<br />
{myArticles ? (
Object.keys(myArticles).map(articleId => {
let article = myArticles[articleId];
let articleInformation = '';
if (article) {
if (
articleId === props.currentPaperId &&
article.hasOwnProperty('year') &&
article.hasOwnProperty('description') &&
article.hasOwnProperty('downloadUrl')
) {
articleInformation =
<div>
<p>{article.year}</p>
<p>{article.description}</p>
<a target="_blank" href={article.downloadUrl}><button className='waves-effect waves-light btn-small'>See article</button></a>
<button className='waves-effect waves-light btn-small' onClick={() => { removeArticle(articleId); }}>Remove from My Articles</button>
</div>;
}
let authorName = '';
if (article.hasOwnProperty('author') && article.author) {
authorName = ` by ${article.author}`;
}
if (article.hasOwnProperty('title') && article.title) {
return <span key={articleId}>
<li onClick={() => { dispatch(selectArticle(articleId)); }}>
<em>{article.title}</em>{authorName}
</li>{articleInformation}
</span>;
} else {
return null;
}
}
})
) : (
<h4>No articles yet</h4>
)
}
</div>
);
} else {
return null;
}
};
const mapStateToProps = (state) => {
return {
currentPaperId: state.currentPaperId,
auth: state.firebase.auth
};
};
export default compose(connect(mapStateToProps))(ArticleList);
Can you show us the error? I think it's about the state not being an array after you delete your data just initialize your state with an empty array like this :
Const= [articlesdata,setArticlesData]=useState([])
And leave the useEffect as it is

Resources