Reputation: 6675
The following code, connects to a Cloud FireStore collection and saves all data in an array called cards using the setCards hook. Next, it maps over cards array and shows all of them on a single page:
import React, { useState, useEffect } from 'react';
import { db } from '../firebase';
const FlipCard = () => {
const [cards, setCards] = useState([]);
useEffect(() => {
const fetchData = async () => {
const data = await db
.collection('FlashCards')
.orderBy('customId', 'asc')
.get();
setCards(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
fetchData();
}, []);
return (
<div className='scene'>
{cards.map((card) => (
<div key={card.id}>
<div>
{card.originalText}
</div>
<div>
{card.translatedText}
</div>
</div>
))}
</div>
);
};
export default FlipCard;
To add pagination to the code, I tried this:
import React, { useState, useEffect } from 'react';
import { db } from '../firebase';
const FlipCard = () => {
const [cards, setCards] = useState([]);
useEffect(() => {
const fetchData = async () => {
const data = await db
.collection('FlashCards')
.orderBy('customId', 'asc')
.limit(1)
.get();
setCards(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
fetchData();
}, []);
const showNext = ({ card }) => {
const fetchNextData = async () => {
const data = await db
.collection('FlashCards')
.orderBy('customId', 'asc')
.limit(1)
.startAfter(card.customId)
.get();
setCards(data.docs.map((doc) => ({ ...doc.data(), id: doc.id })));
};
fetchNextData();
};
return (
<>
<div className='scene'>
{cards.map((card) => (
<div key={card.id}>
<div>
{<img src={card.imgURL} alt='' />}
{card.originalText}
</div>
<div>
{card.translatedText}
</div>
</div>
))}
</div>
<button onClick={showNext}>Next</button>
</>
);
};
export default FlipCard;
But React complains that:
Unhandled Rejection (TypeError): Cannot read property 'customId' of undefined
Is my approach right? How can I fix it?
Upvotes: 3
Views: 862
Reputation: 3396
You received this undefined error because you don't pass the card object in your onClick handler.
In fact, you are passing a synthetic event to your showNext
function by doing this <button onClick={showNext}>Next</button>
.
To actually pass your card object, you have to call your function like this:
<button onClick={() => showNext({card: cards[cards.length - 1]})}>Next</button>
As for your request to comment about your implementation details, I'd put it in the comment as this is an opinion (meaning it could be wrong in certain circumstances)
Upvotes: 1