I want to only show the "Load More" button when I have extra documents to show on my React and Firebase website.
Right now, I'm fetching only 2 documents from a firestore and I want to show the "Load More" button when I have more than 2 documents in my firestore. If I only have 2 or fewer than 2 documents in my firestore, I don't want to show the "Load More" button.
And I want to hide the "Load More" button after fetching all the documents that I have on the firestore.
Anyone, please help me with this!
useCollection Hook:
import { useEffect, useRef, useState } from "react"
// firebase import
import {
collection,
getDocs,
limit,
onSnapshot,
orderBy,
query,
startAfter,
where,
} from "firebase/firestore"
import { db } from "../firebase/config"
export const useCollection = (c, _q, _l, _o) => {
const [documents, setDocuments] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState(null)
// if we don't use a ref --> infinite loop in useEffect
// _query is an array and is "different" on every function call
const q = useRef(_q).current
const o = useRef(_o).current
useEffect(() => {
let ref = collection(db, c)
if (q) {
ref = query(ref, where(...q))
}
if (o) {
ref = query(ref, orderBy(...o))
}
if (_l) {
ref = query(ref, limit(_l))
}
const unsubscribe = onSnapshot(ref, (snapshot) => {
const results = []
snapshot.docs.forEach(
(doc) => {
results.push({ ...doc.data(), id: doc.id })
},
(error) => {
console.log(error)
setError("could not fetch the data")
}
)
// update state
setDocuments(results)
setIsLoading(false)
setError(null)
})
// unsubscribe on unmount
return unsubscribe
}, [])
const fetchMore = async (doc) => {
setIsLoading(true)
const q = query(
collection(db, c),
orderBy(...o),
startAfter(doc.createdAt),
limit(_l)
)
const newDocuments = await getDocs(q)
updateState(newDocuments)
setIsLoading(false)
}
const updateState = (docs) => {
if (!docs.empty) {
const tempPosts = []
docs.forEach((document) => {
tempPosts.push({
id: document.id,
...document.data(),
})
})
setDocuments([...documents, ...tempPosts])
}
}
return { documents, fetchMore, error, isLoading }
}
SolutionComments.js (In this file I'm showing the "Load More Comments" button)
import React, { useState } from "react"
import { useParams } from "react-router-dom"
import { useCollection } from "../../hooks/useCollection"
import Comment from "./Comment"
import CommentForm from "./CommentForm"
const SolutionComments = () => {
const [activeComment, setActiveComment] = useState(null)
const { id } = useParams()
const { documents, fetchMore, isLoading } = useCollection(
`solutions/${id}/comments`,
null,
2,
["createdAt", "desc"]
)
const fetchMoreComments = () => {
fetchMore(documents[documents.length - 1])
}
return (
<div className="mt-10">
<CommentForm docID={id} />
<div>
{documents &&
documents.map((comment) => (
<Comment
key={comment.id}
comment={comment}
replies={comment.replies}
activeComment={activeComment}
setActiveComment={setActiveComment}
/>
))}
</div>
{documents.length > 2 && (
<button onClick={fetchMoreComments} className="text-white bg-purple-500">
{!isLoading ? "Load More Comments!" : "Loading..."}
</button>
)}
</div>
)
}
export default SolutionComments
Firestore does not have a mechanism for automatically telling you how many documents are in a query. You will need to manage that aggregate count yourself. Then you could fetch that aggregate count and use that to determine whether to show a load more button or not.
However this is harder than it sounds. And most modern apps we don't use load more buttons rather we use infinite scroll.
To be honest, it has never been efficient or smart to show a result set count in an app. The fact that people have done it in the past doesn't mean that it is the right thing to do today. It might have made sense when you had small databases, typically running off of a desktop database. But in a cloud-based solution with millions of documents and millions of users, and complex queries, knowing how many documents are in a result set is a very hard problem to solve.
Related
import './App.css';
import OutputBox from './OutputBox';
import React, { useState } from 'react';
import * as functions from "./functions.js"
import axios from 'axios'
function App() {
//define state variables
const [cargo, setCargo] = useState('');
const [acceleration, setAcceleration] = useState('');
const [takeoff_time, setTakeOffTime] = useState('');
const [takeoff_distance, setTakeOffDistance] = useState('');
const [excess_cargo, setExcessCargo] = useState('');
const [date, setDate] = useState();
const [message, setMessage] = useState('');
//send the data to /insert-data in order to store it in the db
const insertData = () => {
axios.post("http://localhost:3001/insert-data", {
takeoff_time: takeoff_time.toString(),
takeoff_distance: takeoff_distance.toString(),
excess_cargo: excess_cargo.toString(),
cargo: cargo.toString()
}).then(()=> {
console.log("success");
}).catch((error) => {
console.error(error);
});
console.log(takeoff_time +" | "+ takeoff_distance+" | "+excess_cargo+" | "+cargo);
};
//get the cargo data
//return if the input is valid
const validInput = (cargo) => {
if (cargo < 0 || isNaN(cargo)) {
alert("invalid input!");
return false;
}
else {
return true;
}
}
//A function that centralizes the actions
const handleData = () => {
if(validInput(cargo)){
//update the variables every time it change
setAcceleration(functions.getAcceleration(cargo));
setTakeOffTime(functions.getTakeOffTime(cargo));
setTakeOffDistance(functions.getTakeOffDistance(cargo));
setExcessCargo(functions.getExcessCargo(cargo));
//call the insert function
insertData();
}
}
//asynchronous func to handle the date data
const handleDate = async () => {
try { //make a post request to send date data to the back-end
const response = await axios.post("http://localhost:3001/date-picker", { date });
setMessage(response.data); //set the changed value to the current variable
}catch(error){ //trying to catch errors
console.log(error);
}
}
//prints to the web the data
return (
<div className='App'>
<div className='data'>
<h1>Shimshon physics calculator</h1>
<label>Enter cargo weight:</label>
<input type="number" onChange={ (event) => {setCargo(event.target.valueAsNumber)}}/>
<button onClick={handleData}>Send data</button>
<OutputBox text={`Acceleration: ${acceleration}`} />
<OutputBox text={`Takeoff Time: ${takeoff_time}`} />
<OutputBox text={`Takeoff Distance: ${takeoff_distance}`} />
<OutputBox text={`Excess Cargo: ${excess_cargo}`} />
<br />
<label>Enter flight date:</label>
<input type= "date" onChange={(event) => { setDate(event.target.value) }} />
<button onClick={handleDate}>Send date</button>
<OutputBox text={`you ${ message } able to filght`} />
</div>
</div>
);
}
export default App;
the problem is when I enter cargo and click send data.
I receive in the table in the db only the entered cargo value, and the other values are empty.
But when I re-enter input for cargo and click on send data I get in the table of the db the value of the current entered cargo and the previous value of (takeoff_time, takeoff_distance, excess_cargo).
any solution pls??
The reason your app behaves like it does has to do with the way states are updated. When calling insertData you update 4 states before calling the axios function. States update asynchronously. That means that your app won't wait for the states to have changed before running the rest of your code. So in practice, insertData will be called before any of the states have been modified, leaving you with empty values.
The solution lies in the way that you handle changed data. Instead of updating the four states when clicking the button, update them immediately after the cargo state has changed.
I'd recommend that you change the acceleration, take off, distance and excess cargo states to into useMemo hooks. This way you'll immediately make the calculations necessary for any future requests without triggering a re-render.
The snippet below is an example of you would implement these practices. I've also added multiple useCallback hooks. Both useMemo and useCallback will store the result based on the states they're dependant on so that the same calculation doesn't have be to done more than once. This is not mandatory, but an optimization.
import './App.css';
import OutputBox from './OutputBox';
import React, { useState, useMemo, useCallback } from 'react';
import axios from 'axios'
import {
getAcceleration,
getTakeOffTime,
getTakeOffDistance,
getExcessCargo
} from "./functions.js"
function App() {
const [cargo, setCargo] = useState(0);
const [date, setDate] = useState();
const [message, setMessage] = useState('');
const isValidCargo = useMemo(() =>
cargo >= 0 && !isNaN(cargo)
}, [cargo]);
const acceleration = useMemo(() =>
getAcceleration(cargo),
[cargo]);
const takeoffTime = useMemo(() =>
getTakeOffTime(cargo),
[cargo]);
const takeoffDistance = useMemo(() =>
getTakeOffDistance(cargo),
[cargo]);
const excessCargo = useMemo(() =>
getExcessCargo(cargo),
[cargo]);
const insertData = useCallback(() => {
axios.post("http://localhost:3001/insert-data", {
takeoff_time: takeoffTime.toString(),
takeoff_distance: takeoffDistance.toString(),
excess_cargo: excessCargo.toString(),
cargo: cargo.toString()
}).then(()=> {
console.log("success");
}).catch((error) => {
console.error(error);
});
}, [takeoffTime, takeoffDistance, excessCargo, cargo]);
const handleData = useCallback(() => {
if (isValidCargo) {
insertData();
}
}, [isValidCargo]);
const handleDate = useCallback(async () => {
try {
const response = await axios.post("http://localhost:3001/date-picker", {
date
});
setMessage(response.data);
} catch (error) {
console.log(error);
}
}, [date]);
return (
<div className='App'>
{/* The rest of your rendered body here */}
</div>
);
}
I'm building an app with React and Firebase Realtime Database. Objects are added to an array and sent to the database.
The arrays are updated in React and the result is sent to the database.
The functionality to remove items/objects from the list works fine when there are more than one (i.e. button clicked, database, DOM and state updated immediately).
However, whenever there's one item left and you click its delete button, it's deleted from the database but the state and React DOM aren't updated - you have to refresh the page for it to be removed.
I've tried using different methods to update the database in case it triggered a different response but that didn't work - any ideas would be greatly appreciated:
import React, {useState, useEffect} from 'react'
import { Button } from "react-bootstrap";
import Exercise from "./Exercise";
import AddNewWorkout from "./AddNewWorkout";
import { v4 as uuidv4 } from "uuid";
import WorkoutComponent from './WorkoutComponent';
import AddNewExercise from "./AddNewExercise"
import { database, set, ref, onValue, update } from "../firebase"
const Dashboard = ({user}) => {
const [selectedWorkout, setSelectedWorkout] = useState();
const [workouts, setWorkouts] = useState([])
const [creatingNewWorkout, setCreatingNewWorkout] = useState(false);
const [addingNewExercise, setAddingNewExercise] = useState(false)
function selectWorkout(number) {
const selection = [...workouts].filter(workout => number == workout.id);
setSelectedWorkout(selection[0])
}
function toggleNewWorkoutStatus(e) {
e.preventDefault()
setCreatingNewWorkout(creatingNewWorkout => !creatingNewWorkout)
}
function toggleNewExerciseStatus() {
setAddingNewExercise(addingNewExercise => !addingNewExercise)
}
function writeData() {
const newWorkouts = [...workouts]
const workoutTitle = document.getElementById("workoutTitle").value || new Date(Date.now()).toString()
const workoutDate = document.getElementById("workoutDate").value;
newWorkouts.push({
id: uuidv4(),
title: workoutTitle,
date: workoutDate,
exercises: []
})
set(ref(database, `${user.uid}/workouts/`), newWorkouts )
}
function addWorkoutToListDB(e) {
e.preventDefault();
writeData(user.uid)
}
function removeWorkoutFromList(id) {
const newWorkouts = [...workouts].filter(workout => id !== workout.id);
update(ref(database, `${user.uid}`), {"workouts": newWorkouts} )
}
function addExerciseToWorkout(e) {
e.preventDefault();
if (selectedWorkout === undefined) {
alert("No workout selected")
return
}
const newWorkouts = [...workouts]
const exerciseID = uuidv4();
const exerciseName = document.getElementById("exerciseName").value
const exerciseSets = document.getElementById("exerciseSets").value
const exerciseReps = document.getElementById("exerciseReps").value
const exerciseWeight = document.getElementById("exerciseWeight").value
const exercisetTarget = document.getElementById("exercisetTarget").checked
const exerciseNotes = document.getElementById("exerciseNotes").value;
const newExercise = {
id: exerciseID,
name: exerciseName,
sets: exerciseSets,
reps: exerciseReps,
weight: `${exerciseWeight}kg`,
target: exercisetTarget,
notes: exerciseNotes,
}
for (let key of newWorkouts) {
if (key.id === selectedWorkout.id) {
if (key.exercises) {
key.exercises.push(newExercise)
} else {
key.exercises = [newExercise]
}
}
}
update(ref(database, `${user.uid}`), {"workouts": newWorkouts} )
}
function removeExerciseFromWorkout(id) {
const newWorkouts = [...workouts];
for (let workout of newWorkouts) {
if(selectedWorkout.id === workout.id) {
if (!workout.exercises) {return}
workout.exercises = workout.exercises.filter(exercise => exercise.id !== id)
}
}
const newSelectedWorkout = {...selectedWorkout}
newSelectedWorkout.exercises = newSelectedWorkout.exercises.filter(exercise => exercise.id !== id)
setSelectedWorkout(newSelectedWorkout)
update(ref(database, `${user.uid}`), {"workouts": newWorkouts} )
}
useEffect(() => {
function getWorkoutData() {
const dbRef = ref(database, `${user.uid}`);
onValue(dbRef, snapshot => {
if (snapshot.val()) {
console.log(snapshot.val().workouts)
setWorkouts(workouts => workouts = snapshot.val().workouts)
}
}
)
}
getWorkoutData()
},[])
return (
<div>
{creatingNewWorkout && <AddNewWorkout addWorkoutToListDB={addWorkoutToListDB} toggleNewWorkoutStatus={toggleNewWorkoutStatus} /> }
<div id="workoutDiv">
<h2>Workouts</h2><p>{selectedWorkout ? selectedWorkout.title : "No workout selected"}</p>
<Button type="button" onClick={toggleNewWorkoutStatus} className="btn btn-primary">Add New Workout</Button>
{workouts && workouts.map(workout => <WorkoutComponent key={workout.id} removeWorkoutFromList={removeWorkoutFromList} selectWorkout={selectWorkout} workout={workout}/> )}
</div>
<div>
<h2>Exercise</h2>
{addingNewExercise && <AddNewExercise selectedWorkout={selectedWorkout} addExerciseToWorkout={addExerciseToWorkout} toggleNewExerciseStatus={toggleNewExerciseStatus}/> }
<Button type="button" onClick={toggleNewExerciseStatus} className="btn btn-primary">Add New Exercise</Button>
{selectedWorkout && selectedWorkout.exercises && selectedWorkout.exercises.map(exercise => <Exercise removeExerciseFromWorkout={removeExerciseFromWorkout} key={exercise.id} exercise={exercise}/>)}
</div>
</div>
)
}
export default Dashboard
If it helps, the data flow I'm working to is:
New array copied from state
New array updated as necessary
New array sent to database
Database listener triggers download of new array
New array saved to state
I have tried to use different methods (set, update and remove) in case that triggered the onValue function.
I have also tried to send null values and deleting empty nodes if the array that will be sent to the db is empty.
The above methods didn't have any impact, there was still a problem with the last array element that was only resolved by refreshing the browser.
I have tried to remove the array dependency and add the workout state as a dependency, resulting in the following error: "Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render."
I think I understand where the issue was:
In the useEffect call, I set up the state to only be updated if the value in returned from the database was null (to prevent an error I ran into). However, this meant that state wasn't being updated at all when I deleted the last item from the array.
I appear to have fixed this by adding an else clause.
useEffect(() => {
function getWorkoutData() {
const dbRef = ref(database, `${user.uid}`);
onValue(dbRef, snapshot => {
if (snapshot.val()) {
console.log(snapshot.val().workouts)
setWorkouts(workouts => workouts = snapshot.val().workouts)
} else {
setWorkouts(workouts => workouts = [])
}
}
)
}
getWorkoutData()
},[])
`````
I encountered a problem in my chat app.
I works when I post message doc to the messages col but then I'm trying do getDocs back and render them I get an empty array.
I looked through FB docs, and I didn't notice any mistakes on my part. I also read an article where I was advised to use the react-firebase library with useCollectionData with which I had the same result.
const [messages, loading] = useCollectionData(
firestore.collection('messages').orderBy('createdAt')
)
I tried different approaches but nothing seems to work.
import React, { useState, useEffect } from 'react'
import { auth, db, app } from '../../firebase.config'
import { useAuthState } from 'react-firebase-hooks/auth'
import { useCollectionData } from 'react-firebase-hooks/firestore'
import { docs, onSnapshot, query, where, addDoc, collection, serverTimestamp, orderBy, getDocs } from 'firebase/firestore'
import Message from '../Message/Message'
import Spinner from '../Spinner/Spinner'
import './chat.css'
const Chat = () => {
const [user, loading, error] = useAuthState(auth)
const [value, setValue] = useState('')
const [msgs, setMsgs] = useState([])
console.log('msgs>>>>', msgs)
useEffect(() => {
const fetchMsg = async () => {
const messagesRef = collection(db, 'messages')
const q = query(
messagesRef,
orderBy('timestamp', 'desc')
)
const querySnap = await getDocs(q)
let listings = []
querySnap.forEach((doc) => {
return listings.push({
id: doc.id,
data: doc.data(),
})
})
setMsgs(listings)
}
fetchMsg()
}, [])
const sendMessage = async (e) => {
e.preventDefault();
const docRef = await addDoc(collection(db, 'messages'), {
uid: user.uid,
displayName: user.displayName,
photoURL: user.photoURL,
text: value,
createdAt: serverTimestamp()
})
console.log(docRef)
setValue('')
}
if (loading) {
return <Spinner />
}
return (
<>
<div className='ch-wind'>
{msgs.map((msg) => (
<Message key={msg.id} msg={msg} style={{ backgroundColor: user.uid === msg.uid ? '#A32cc4' : '#a1045a' }} />
))}
</div>
<form className="ch-form" onSubmit={sendMessage}>
<textarea
value={value}
className='ch-form-text'
onChange={e => setValue(e.target.value)}
placeholder='Enter your message here'
/>
<button
className='ch-form-btn'
>
Send
</button>
</form>
</>
)
}
export default Chat
By using useEffect() hook, I would assume that you want to get the data realtime. Firestore has a realtime listeners that you can use. You can listen to a document with the onSnapshot() method. An initial call using the callback you provide creates a document snapshot immediately with the current contents of the single document. Then, each time the contents change, another call updates the document snapshot. See code below:
useEffect(() => {
const messagesRef = query(collection(db, 'messages'), orderBy('timestamp', 'desc'));
onSnapshot(messagesRef, (snapshot) => {
// Maps the documents and sets them to the `msgs` state.
setMsgs(snapshot.docs.map(doc => ({
id: doc.id,
data: doc.data()
})))
})
}, [])
Also, as pointed out by #CDoe, you should use the same Fieldname which you set from the addDoc method as you can see on the above code.
Then on the rendering, something like this:
{msgs.map((msg) => (
// By setting the `doc.data()` to the object `data`, you should access it by `msg.data.<object_key>`
<Message key={msg.id} msg={msg.data.text} style={{ backgroundColor: user.uid === msg.data.uid ? '#A32cc4' : '#a1045a' }} />
))}
I leave some comments on the code to better understand it.
For more information on realtime updates, you may check out this documentation.
In the query, you're trying to orderBy timestamp. That's not a field you're creating in sendMessage.
When a value you're ordering by doesn't exist on the document, it won't return.
Maybe you meant to orderyBy the createdAt value.
const q = query(
messagesRef,
orderBy('createdAt', 'desc')
)
my problem is that I have two different components belonging to my App.js project. It's a movie database where I have a list of movies on the front page and I can search for other movies using the search bar. Since I have the search.js and movie.js ( component where i fetch api data and display), the search.js will not trigger as it cant pinpoint what needs to change. Basically my problem is that on submit, nothing changes.
search.js code:
import { useState } from 'react';
import React from 'react';
// search API used to search through database
const searchUrl = "https://api.themoviedb.org/3/search/movie?api_key=d62e1adb9803081c0be5a74ca826bdbd&query="
const Search = ({ }) => {
const [movies, setMovies] = useState([]);
const [search, setSearch] = useState("");
// Search form that fetches search API and returns results
const submitForm = (e) => {
e.preventDefault();
// API used to search for any movie in the database
fetch(searchUrl + search)
.then(res => res.json())
.then(data => {
setMovies(data.results);
})
setSearch("");}
// user search input
const searchQuery = (e) => {
setSearch(e.target.value)
}
return (
<form onSubmit={submitForm}>
<i class="fas fa-search"></i>
<label className="sr-only" htmlFor="searchMovie">Search for a movie</label>
<input
className="search"
type="search"
placeholder="Search for a movie.."
value={search}
onChange={searchQuery}
/>
</form>
)
}
export default Search;
and my movie.js
import { Link } from 'react-router-dom';
import { useState, useEffect } from "react";
const images = "https://image.tmdb.org/t/p/w500/";
// main API used to display trending page
const apiUrl = `https://api.themoviedb.org/3/movie/now_playing?api_key=d62e1adb9803081c0be5a74ca826bdbd&page=`;
const Movie = ( {
}) => {
const [movies, setMovies] = useState([]);
useEffect(() => {
fetch(apiUrl)
.then((res) => res.json())
.then((data)=> {
setMovies(data.results)
})
}, []);
return (
<section className="movieslist">
{movies.length > 0 ? movies.map((movie) => {
return (
<Link to={`/movie/${movie.id}`}>
<div className="moviePoster">
<img src={movie.poster_path ? `${images}${movie.poster_path}` : "https://www.movienewz.com/img/films/poster-holder.jpg"} alt={movie.title} />
<div className="movieInfo">
<h2>{movie.title}</h2>
<p className="voteStyle">Rating: {movie.voteAverage}</p>
<p className="release">Release Date: {movie.release}</p>
<p className="summary">{movie.overview}</p>
<p className="key">{movie.id}</p>
</div>
</div>
</Link>
);
}): <p class="noResults">No results found. Please try again?</p>}
</section>
)
}
export default Movie;
If I understand the expected behavior correctly, you're trying to update the movies state in movies.js from the search.js.
You are updating two different states of two different components that have no relationship with themselves and that is why nothing is happening on submit.
What you'll need is a parent component (for example home.js) that holds search and movies component as children and holds the movies state. The child components should use and update the parent's movie state.
import Movies from "./movies";
import Search from "./search";
const Home = ()=>{
const [movies, setMovies] = useState([]);
// some other code
return (
<>
<Search onSearh={setMovies} />
<Movies movies={movies} onMovies={setMovies}/>
</>);
}
and your movies.js and search.js should consume these props
import { useState } from 'react';
import React from 'react';
// search API used to search through database
const searchUrl = "https://api.themoviedb.org/3/search/movie?api_key=d62e1adb9803081c0be5a74ca826bdbd&query="
const Search = ({ onSearch }) => {
const [search, setSearch] = useState("");
// Search form that fetches search API and returns results
const submitForm = (e) => {
e.preventDefault();
// API used to search for any movie in the database
fetch(searchUrl + search)
.then(res => res.json())
.then(data => {
onSearch(data.results);
})
setSearch("");}
...
import { Link } from 'react-router-dom';
import { useState, useEffect } from "react";
const images = "https://image.tmdb.org/t/p/w500/";
// main API used to display trending page
const apiUrl = `https://api.themoviedb.org/3/movie/now_playing?api_key=d62e1adb9803081c0be5a74ca826bdbd&page=`;
const Movie = ( {movies, onMovies}) => {
useEffect(() => {
fetch(apiUrl)
.then((res) => res.json())
.then((data)=> {
onMovies(data.results)
})
}, []);
...
this is my react code here I am getting react poll using API but when I start working on handalchange For POST API request I need (PollId,userId and answer) I am getting userId through { const userId = isAutheticated() && isAutheticated().user._id; } but I do not understand how can I get PollId from my all polls, please help...!
import React, { useState, useEffect } from "react";
import Poll from "react-polls";
import "../../styles.css";
import { isAutheticated } from "../../auth/helper/index";
import { getPolls, postPoll } from "../helper/coreapicalls";
import { useParams } from "react-router-dom";
const MainPoll = () => {
const userId = isAutheticated() && isAutheticated().user._id;
const pollId = useParams();
const id = pollId._Id;
console.log(id);
const [polls, setPoll] = useState([]);
const [error, seterror] = useState(false);
// Setting answers to state to reload the component with each vote
const [pollAnswers, setPollAnswers] = useState([]);
useEffect(() => {
loadPoll();
}, []);
const loadPoll = () => {
getPolls().then((data) => {
if (data.error) {
seterror(data.error);
} else {
setPoll(data);
console.log(data);
}
});
};
// Handling user vote
// Increments the votes count of answer when the user votes
const handalchange = () => {
postPoll();
console.log("hello");
};
return (
<div className="">
<div className="container my-5">
<h1 className="blog_heading my-3">Poll's of the Day</h1>
<div className="row">
{polls.reverse().map((poll, index) => (
<div className="col-lg-4 col-12 poll_border" key={index}>
<Poll
noStorage
question={poll.question}
answers={Object.keys(poll.options).map((key) => {
return {
option: key,
votes: poll.options[key].length,
};
})}
onVote={handalchange}
className="mb-2"
/>
</div>
))}
</div>
</div>
</div>
);
};
export default MainPoll;
my frontend image -
Here I have 5 polls , so I can not get PollId from useParams ...! so how can I get..?
Your component seems to represent list of polls, not any specific poll. So if you have an array of polls instead of one poll, than you have multiple ids instead of the single one.
You can get them by mapping your polls array like that:
const pollIds = polls.map((poll) => poll.id); // or any other prop that stores id