React pagination with dots - reactjs

I create a react pagination component. Typical pagination logic, nothing especial, but I can not add dots logic, for example like this: < 1 2 ... 20 > when I could add the dots after certain page number and before last one. Also this dots element necessary to move while clicking forward like this: < 1 ... 5 6 ... 20 >
How to do it by right way?
export const Pagination = ({ newsList }) => {
const pageNumberLimit = 3;
const [posts, setPosts] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [maxPageLimit, setMaxPageLimit] = useState(4);
const [minPageLimit, setMinPageLimit] = useState(0);
const [postsPerPage] = useState(3);
const totalPosts = posts.length;
const lastPostIndex = currentPage * postsPerPage;
const firstPostIndex = lastPostIndex - postsPerPage;
const currentPost = posts.slice(firstPostIndex, lastPostIndex);
const paginate = (pageNumber) => setCurrentPage(pageNumber);
const pageNumbers = [];
for (let i = 1; i <= Math.ceil(totalPosts / postsPerPage); i++) {
pageNumbers.push(i);
}
const prevPage = () => {
setCurrentPage((prev) => prev - 1);
};
const nextPage = () => {
setCurrentPage((prev) => prev + 1);
};
useEffect(() => {
const getPosts = () => {
setPosts(newsList);
};
getPosts();
}, []);
return (
<div className="paginationPerPage">
{currentPost.map() => (
<div className="card"/>
))}
<ul className="ctyledPageNumbers">
<button className="styledPageNumbersButton" onClick={prevPage} type="button" disabled={currentPage === pageNumbers[0]}>
‹ Anterior
</button>
{pageNumbers.map((number) => {
if (number >= maxPageLimit && number < pageNumbers.length) {
return (
<button onClick={nextPage} type="button">
…
</button>
);
}
return (
<li key={number} className={currentPage === number ? 'active' : null}>
<button type="button" onClick={() => paginate(number)}>
{number}
</button>
</li>
);
})}
<button className="styledPageNumbersButton"
onClick={nextPage}
type="button"
disabled={currentPage === pageNumbers[pageNumbers.length - 1]}
>
Seguinte ›
</button>
</ul>
</div>
);
};

Related

After clicking add icon in one image model all images in that row gets clicked //ReactJs

I want to add the images to mylist component by clicking the add icon but after clicking the add icon on image model(appears after clicking the image) the icon on all images of that row gets clicked.How to make the icon of that particular image model(appears after clicking the image) only clicked .
Actually i want to use firestore to store all the movies that are clicked (added) in the mylist component.
The code is below :-
function Slider({ rowtitle, type }) {
let img_path = "https://image.tmdb.org/t/p/w500";
let base_url = "https://api.themoviedb.org/3";
let url = base_url + type;
const [movieData, setData] = useState([]);
const [url_set, setUrl] = useState(url);
useEffect(() => {
fetch(url_set)
.then((res) => res.json())
.then((data) => {
setData(data.results);
});
}, [url_set]);
const [isOpen, setIsOpen] = useState(false);
const [title, setTitle] = useState();
const [overview, setOverview] = useState();
const [release, setRelease] = useState();
const [poster, setPoster] = useState();
const [backdrop, setBackdrop] = useState();
const [idd, setIDD] = useState();
const handleClicked = (movie) => {
setTitle(movie?.name || movie?.original_title);
setOverview(movie?.overview);
setRelease(movie?.release_date || movie?.first_air_date);
setPoster(movie?.poster_path);
setBackdrop(movie?.backdrop_path);
setIDD(movie?.id);
};
const [like, setLike] = useState(false);
const [DisLike, setDisLike] = useState(false);
const togglelike = () => {
if (DisLike) {
setDisLike(false);
setLike(true);
} else {
setLike(!like);
}
};
const toggledislike = () => {
if (like) {
setLike(false);
setDisLike(true);
} else {
setDisLike(!DisLike);
}
};
const [add, setAdd] = useState(false);
const [saved, setSaved] = useState(false);
const { user } = useUserAuth();
const movieID = doc(db, "users", `${user?.email}`);
const saveShow = async () => {
if (user?.email) {
setAdd(!add);
setSaved(true);
await updateDoc(movieID, {
savedShows: arrayUnion({
id: idd,
title: title,
img: backdrop,
}),
});
} else {
alert("please sign in to add movies to list");
}
};
const handleADD = () => {
saveShow();
};
return (
<div className="slidermain">
<div className="slidertitle">{rowtitle}</div>
<div className="slider">
**For popup model after clicking image**
<Modal className="popup" open={isOpen} onClose={() => setIsOpen(false)}>
<div className="modalinside">
<div className="modalcontent">
<div className="modaltitle">
<h1>{title}</h1>
</div>
<div className="modaldesc">{overview}</div>
<div className="modalicons">
<BiPlay className="modalicon" />
<p onClick={handleADD}>
<AiOutlinePlus
className={add ? "modalicon clickmodalicon" : "modalicon"}
/>
</p>
<BiLike
className={like ? " modaliconclick" : "modalicon"}
onClick={togglelike}
/>
<BiDislike
className={DisLike ? " modaliconclick" : "modalicon"}
onClick={toggledislike}
/>
</div>
<div className="modalrelease"> Release : {release}</div>
</div>
<div className="modalimg">
<img src={img_path + poster || backdrop} alt="poster" />
</div>
</div>
</Modal>
** For List of images ***
<div className="mainslider">
{movieData.map((res, pos) => {
return (
<div onClick={() => handleClicked(res)}>
<img
src={img_path + res.poster_path}
onClick={() => setIsOpen(true)}
alt="poster"
key={idd}
onError={(e) => (e.target.style.display = "none")}
/>
</div>
);
})}
</div>
</div>
</div>
);
}

Get the Category ID of a button in React

I'm trying to get the value of the category ID on a click of a button but it's getting all the id's of my category when I click one of the buttons.
const CategoryPage = ({ categories }) => {
const classes = useStyles()
const [click, setClick] = useState()
const handleClick = (e) => {
e.preventDefault()
const id = categories.map((category) => category._id)
console.log(id)
}
return (
<div className={classes.scrollMenu}>
{categories.map((category) => {
return (
<Button
key={category._id}
className={classes.button}
onClick={(e) => handleClick(e)}
>
{category.name}
</Button>
)
})}
</div>
)
}
You can pass the category.id as the argument to the caller function.
const CategoryPage = ({ categories }) => {
const classes = useStyles()
const [click, setClick] = useState()
const handleClick = (categoryId) => { // clicked category id
e.preventDefault()
console.log(categoryId)
}
return (
<div className={classes.scrollMenu}>
{categories.map((category) => {
return (
<Button
key={category._id}
className={classes.button}
onClick={() => handleClick(category._id)} // this way
>
{category.name}
</Button>
)
})}
</div>
)
}

How to passing functions to components?

I am doing the implementation of list pagination through a custom hook. The handleSetCurrentPage() function gets the correct number, it uses setCurrentPage(number). Consolelog setCurrentPage(number) showed undefined.
if you do all the same code only within one file (put everything in ListOfItems) it works fine.
Hook:
export const usePagination = (users = [], defaultPage = 1, amountPerPage = 10) => {
const [currentPage, setCurrentPage] = useState(defaultPage);
const [currentUsers, setCurrentUsers] = useState([]);
const [amountOfPages, setAmountOfPages] = useState(0);
useEffect(() => {
updateUsers();
updateAmountOfPages();
}, []);
const updateUsers = () => {
const indexOfLastPost = currentPage * amountPerPage;
const indexOfFirstPost = indexOfLastPost - amountPerPage;
const updatedUsers = users.slice(indexOfFirstPost, indexOfLastPost);
setCurrentUsers(updatedUsers);
};
const updateAmountOfPages = () => {
const updatedAmount = Math.ceil(users.length / amountPerPage);
setAmountOfPages(updatedAmount);
};
return {
setCurrentPage,
amountOfPages,
currentUsers,
};
};
list of items:
export function ListOfItems() {
const users = useSelector(state => state);
const { setCurrentPage, currentUsers, amountOfPages } = usePagination(users);
let {url} = useRouteMatch();
let items = currentUsers.map(function (value, index) {
return (
<form key={index}>
<div className="input-group">
<div className="input-group-prepend">
<Link className="input-group-text" to={`${url}/${index}`}>
{value.name}, {index}
</Link>
</div>
</div>
</form>
)
});
return (
<div>
{/*<form className="card">*/}
{/* <Search setSearch={setSearch} />*/}
{/*</form>*/}
<div>{items}</div>
<div>
<Pagination amountOfPages={amountOfPages} setCurrentPage={setCurrentPage}/>
</div>
</div>
)
}
pagination component:
const Pagination = ({amountOfPages, setCurrentPage}) => {
const [pageNumbers, setPageNumbers] = useState([]);
useEffect(() => {
calculatePageNumbers();
}, [amountOfPages]);
function calculatePageNumbers() {
const updatedPageNumbers = [];
for (let i = 1; i <= amountOfPages; i++) {
updatedPageNumbers.push(i);
}
setPageNumbers(updatedPageNumbers);
}
function handleSetCurrentPage(number) {
console.log(number);
return console.log(setCurrentPage(number));
}
return (
<nav>
<ul className="pagination">
{pageNumbers.map(number => (
<li key={number} className="page-item">
<button
onClick={() => handleSetCurrentPage(number)}
type="button"
className="page-link"
>
{number}
</button>
</li>
))}
</ul>
</nav>
);
};
export default Pagination;
useEffect(() => {
updateUsers();
updateAmountOfPages();
}, [currentPage]);

Reduce onIncrement() and onDecrement() to 1 function Reactjs?

I am coding a counters app. So I want to replace onIncrement, onDecrement function by onChange function.
I want to remove onIncrement and onDecrement function. Then I want to add new onChange function
The onChange function should take a single parameter and it can decrement or increment a counter.
my code:
const Counter = props => {
const { onIncrement, onDecrement, count, index } = props;
return (
<div className="counter">
<b>{count}</b>
<div className="counter-controls">
<button
onClick={() => onDecrement(index)}
className="button is-danger is-small"
>
-
</button>
<button
onClick={() => onIncrement(index)}
className="button is-success is-small"
>
+
</button>
</div>
</div>
);
};
const Total = props => {
const { sum } = props;
return (
<div>
<p>Total: {sum} </p>
</div>
);
};
export default function App() {
const [data, setData] = useState([
{ id: 1, value: 0 },
{ id: 2, value: 0 },
{ id: 3, value: 0 }
]);
const total = data.map(item => item.value).reduce((p, n) => p + n);
const [sum, setSum] = useState(total);
const handleIncrement = index => {
const clone = [...data];
clone[index - 1].value += 1;
setData(clone);
setSum(sum + 1);
};
const handleDecrement = index => {
const clone = [...data];
clone[index - 1].value -= 1;
setData(clone);
setSum(sum - 1);
};
return (
<div className="App">
{data.map(counter => (
<Counter
key={counter.id}
onIncrement={handleIncrement}
onDecrement={handleDecrement}
index={counter.id}
count={counter.value}
/>
))}
<Total sum={sum} />
</div>
);
}
You can write a single onChange function and pass on the change value while calling the function. Use the changeValue to add to the previous data. For a decrement implementation change value will be -1 and for increment it will be +1
const Counter = props => {
const { onChange, count, index } = props;
return (
<div className="counter">
<b>{count}</b>
<div className="counter-controls">
<button
onClick={() => onChange(index, -1)}
className="button is-danger is-small"
>
-
</button>
<button
onClick={() => onChange(index, 1)}
className="button is-success is-small"
>
+
</button>
</div>
</div>
);
};
const Total = props => {
const { sum } = props;
return (
<div>
<p>Total: {sum} </p>
</div>
);
};
export default function App() {
const [data, setData] = useState([
{ id: 1, value: 0 },
{ id: 2, value: 0 },
{ id: 3, value: 0 }
]);
const total = data.map(item => item.value).reduce((p, n) => p + n);
const [sum, setSum] = useState(total);
const handleChange = (index, changeValue) => {
const clone = [...data];
clone[index - 1].value += changeValue;
setData(clone);
setSum(prevSum = prevSum + changeValue);
};
return (
<div className="App">
{data.map(counter => (
<Counter
key={counter.id}
onChange={handleChange}
index={counter.id}
count={counter.value}
/>
))}
<Total sum={sum} />
</div>
);
}

How to make page number one as a default page

Using React.js, When I change between filters buttons, I want pagination get back to the first page (number one).
This is my code in pagination component:
import React, { useState } from 'react'
const Pagination = ({productsPerPage, totalPosts, paginate}) => {
const [currentPage, setCurrentPage] = useState(1)
const PageNumbers =[]
const int = Math.ceil(totalPosts / productsPerPage)
for (let i = 1; i<= int; i++) {
PageNumbers.push(i)
}
return (
<nav className="">
<ul className="pagination">
<li className={currentPage === 1 ? 'disabled' : ''}>
<a onClick={() =>{setCurrentPage(currentPage - 1); paginate(currentPage - 1);}}>Previous</a>
</li>
{PageNumbers.map(number => (
<li
key={number}
className={number === currentPage ? "page-item active" : "page-item "}
>
<a
onClick={() => paginate(number)}
href="!#"
className="page-link "
>
{number}
</a>
</li>
))}
<li className={currentPage === int ? 'disabled' : ''}>
<a onClick={() => {setCurrentPage(currentPage + 1); paginate(currentPage + 1); }}>Next</a>
</li>
</ul>
</nav>
)
}
export default Pagination
This is the main App
const App = () => {
const [itemsAmount] = useState(100);
const [fromProduct, setFromProduct] = useState(1);
const [keys, setKeys] = useState([]);
const [products, setProducts] = useState([]);
const [currentPage, setCurrentPage] = useState(1);
const [productsPerPage, setProductsPerPage] = useState(10);
useEffect(() => {
axios('The API link')
.then(res => {
setProducts(res.data.itemsList);
res.data.itemsList[0] &&
setKeys(Object.keys(res.data.itemsList[0]).map((key, index) => key));
})
}, [Organization, HardWareStatuses, hardvarutyp, fromProduct,
itemsAmount,setProductsPerPage]);
/* Get current products*/
const indexOfLastProduct = currentPage * productsPerPage;
const indexOfFirstProduct = indexOfLastProduct - productsPerPage;
const currentProducts =
products.slice(indexOfFirstProduct,indexOfLastProduct );
/* Change page */
const paginate = pageNumber => setCurrentPage(pageNumber)
return (
<div>
{/* Create pagination */}
<div className="">
<Pagination
productsPerPage={productsPerPage}
totalProducts={products.length}
paginate={paginate}
filters ={filters}
/>
</div>
</div>
<Products products={currentProducts} keys={keys} />
<ExportCSV products={products} keys={keys} />
</div>
);
};
export default App;
Your pagination component need to be aware about your filters, and I guess those are managed by a parent component. One easy way would be to add them as parameters to your component to make it aware of them.
<Pagination productsPerPage="productsPerPage" totalPosts="totalPosts" paginate="paginate" filters="filters"/>
This way, you can implement a listenner to run some code only when filters change, using the useEffect hook:
import React, { useState, useEffect } from 'react'
const Pagination = ({productsPerPage, totalPosts, paginate, filters}) => {
const [currentPage, setCurrentPage] = useState(1)
const PageNumbers =[]
const int = Math.ceil(totalPosts / productsPerPage)
useEffect(() => {
setCurrentPage(1);
}, [filters]);
for (let i = 1; i<= int; i++) {
PageNumbers.push(i)
}
return (
<nav className="">
...
</nav>
)
}
export default Pagination;

Resources