It is my first time working with useContext hook and I was trying to consume values with useContext in Navbar.js which I've provided in the parent component, but i'm receiving undefined only. In the Navbar.js when I console log user it showsundefined.
I tried to pass the data as props and it works fine. It only happens when I try with Context API. I think I messed up my context api implementation.
Created a context at AuthContext.js
import {createContext} from 'react'
export const AuthContext = createContext({})
Set values in App.js and wrapped using Provider.
import Login from "./pages/Login";
import Register from "./pages/Register";
import Cart from "./components/Cart/Cart";
import Slider from "./components/Slider";
import Categories from "./components/Categories";
import PopularProducts from "./components/PopularProducts";
import Navbar from "./components/Navbar";
import Checkout from "./components/Cart/Checkout";
import Products from "./components/Products";
import Footer from "./components/Footer";
import {
signInWithEmailAndPassword,
signOut,
onAuthStateChanged,
createUserWithEmailAndPassword,
} from "firebase/auth";
import { auth } from "./lib/firebase-config";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import { useState, useEffect } from "react";
import { commerce } from "./lib/commerce";
import { AuthContext } from "./context/AuthContext";
const App = () => {
const [products, setProducts] = useState([]);
const [cart, setCart] = useState({});
const [order, setOrder] = useState({});
const [errorMessage, setErrorMessage] = useState("");
const [loginEmail, setLoginEmail] = useState("");
const [loginPassword, setLoginPassword] = useState("");
const [user, setUser] = useState({});
const [registerEmail, setRegisterEmail] = useState("");
const [registerPassword, setRegisterPassword] = useState("");
const [isLoggedIn, setIsLoggedIn] = useState(
localStorage.getItem("isLoggedIn")
);
onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
});
const loginHandler = async (event) => {
event.preventDefault();
try {
const user = await signInWithEmailAndPassword(
auth,
loginEmail,
loginPassword
);
setIsLoggedIn(true);
localStorage.setItem("isLoggedIn", true);
console.log(auth.currentUser.email);
} catch (error) {
console.log(error.message);
}
};
const registerHandler = async () => {
try {
const user = await createUserWithEmailAndPassword(
auth,
registerEmail,
registerPassword
);
setIsLoggedIn(true);
localStorage.setItem("isLoggedIn", true);
console.log({ registerEmail });
console.log(user);
} catch (error) {
console.log(error.message);
}
};
const logoutHandler = async () => {
await signOut(auth);
setIsLoggedIn(false);
localStorage.clear();
};
const fetchProducts = async () => {
const { data } = await commerce.products.list();
setProducts(data);
};
const fetchCart = async () => {
setCart(await commerce.cart.retrieve());
};
const handleAddToCart = async (productId, quantity) => {
const item = await commerce.cart.add(productId, quantity);
setCart(item.cart);
};
const handleUpdateCartQty = async (lineItemId, quantity) => {
const response = await commerce.cart.update(lineItemId, { quantity });
setCart(response.cart);
};
const handleRemoveFromCart = async (lineItemId) => {
const response = await commerce.cart.remove(lineItemId);
setCart(response.cart);
};
const handleEmptyCart = async () => {
const response = await commerce.cart.empty();
setCart(response.cart);
};
const refreshCart = async () => {
const newCart = await commerce.cart.refresh();
setCart(newCart);
};
const handleCaptureCheckout = async (checkoutTokenId, newOrder) => {
try {
const incomingOrder = await commerce.checkout.capture(
checkoutTokenId,
newOrder
);
setOrder(incomingOrder);
refreshCart();
} catch (error) {
setErrorMessage(error.data.error.message);
console.log(error.data);
}
};
useEffect(() => {
fetchProducts();
fetchCart();
}, []);
return (
<>
<AuthContext.Provider
value={
(user,
logoutHandler,
isLoggedIn) }>
<Navbar/>
</AuthContext.Provider>
</>
);
};
export default App;
Trying to consume data using useContext in Navbar.js
import { Badge } from "#material-ui/core";
import {
Search,
ShoppingCartOutlined,
TranslateOutlined,
} from "#material-ui/icons";
import { useContext } from "react";
import styled from "styled-components";
import { mobile } from "../responsive";
import { Link } from "react-router-dom";
import { AuthContext } from "../context/AuthContext";
const Parent = styled.div``;
const Container = styled.div`
height: 70px;
background-color: #b6e7f0;
${mobile({ height: "70px" })}
width: 98.75vw;
position: fixed;
top: 0;
z-index: 4;
`;
const Logo = styled.h4`
font-size: 30px;
color: black;
margin-left: 20px;
${mobile({ fontSize: "30px" })}
`;
const Wrapper = styled.div`
padding: 10px 0px;
display: flex;
justify-content: space-between;
max-width: 98.75vw;
${mobile({ padding: "10px 0px" })}
`;
const Left = styled.div`
display: flex;
align-items: center;
text-decoration: none;
width: 20%;
`;
const Center = styled.div``;
const Right = styled.div`
display: flex;
align-items: center;
margin-right: 20px;
justify-content: flex-end;
text-decoration: none;
${mobile({ flex: 2, justifyContent: "flexEnd" })}
`;
const Language = styled.span`
font-size: 14px;
cursor: pointer;
${mobile({ display: "none" })}
`;
const SearchContainer = styled.div`
flex: 1;
display: flex;
align-items: center;
margin-left: 0px;
margin-top: 10px;
padding: 5 px;
border-radius: 5px;
cursor: pointer;
${mobile({ display: "none" })}
&:focus {
}
`;
const Input = styled.input`
border: none;
&:focus {
outline: none;
}
width: 90%;
height: 100%;
border-radius: 5px;
font-size: 15px;
padding: 5px;
margin-right: 20px;
${mobile({ height: "50%" })}
`;
const MenuItem = styled.div`
margin-left: 25px;
margin-top: 3px;
font-size: 18px;
font-weight: 600;
color: #0a6596e6;
cursor: pointer;
justify-content: space-between;
${mobile({ fontSize: "13px", marginLeft: "10px" })}
`;
const Navbar = () => {
const { user, logoutHandler, isLoggedIn } = useContext(AuthContext);
console.log(user)
return (
<Parent>
<Container>
<Wrapper>
<Left>
<Link to={"/"}>
<Logo>audiobae</Logo>
</Link>
</Left>
<SearchContainer style={{ color: "gray", fontSize: 14 }}>
<Input placeholder="Search for products, brands and more" />
<Search style={{ fontSize: "30px" }} />
</SearchContainer>
<Right>
<Language style={{ marginLeft: "5px", marginTop: "3px" }}>
<TranslateOutlined />
</Language>
{console.log(isLoggedIn)}
{isLoggedIn ? (
<>
<MenuItem>{user?.email}</MenuItem>
<MenuItem onClick={logoutHandler}>Logout</MenuItem>
</>
) : (
<>
<Link to={"/register"} style={{ textDecoration: "none" }}>
<MenuItem>Register </MenuItem>
</Link>
<Link to={"/login"} style={{ textDecoration: "none" }}>
<MenuItem>Login</MenuItem>
</Link>
</>
)}
<MenuItem>
<Link to={"/cart"}>
<Badge badgeContent={cart?.total_items} color="primary">
{console.log(cart)}
<MenuItem>
<ShoppingCartOutlined />
</MenuItem>
</Badge>
</Link>
</MenuItem>
</Right>
</Wrapper>
</Container>
</Parent>
);
};
export default Navbar;
try it
<AuthContext.Provider value={{user,logoutHandler,isLoggedIn}}>
<Navbar/>
</AuthContext.Provider>
Related
There are three components Toggle, ToggleMenu, Wrapper
The toggle should be universal, and used for different functions
The Wrapper should only change background color when toggle is on
The question is how to pass the function that responcible for changing color to togglemenu, that it executs when switch toggle
App
import React from 'react';
import { Wrapper } from './containers/wrapper';
import { Button } from './components/buttons/button';
import { ToggleMenu } from './components/settings/settings';
const App = () => {
return (
<>
<Wrapper>
<Button />
<ToggleMenu />
</Wrapper>
</>
)
}
export default App;
ToggleMenu
import styled from "styled-components";
import { Toggle } from "../buttons/toggle";
import { WrapperProps } from "../../containers/wrapper";
import { test } from "./test"
const SettingsContainer = styled.div`
margin: auto;
width: 50%;
height: 50%;
display: flex;
align-items: center;
justify-content: center;
background-color: white;
`;
const Container = styled.div`
height: 50%;
width: 50%;
display: flex;
justify-content: center;
flex-direction: column;
background-color: lime;
`;
const TogCon = styled.div`
margin: 0.5em;
`;
export const ToggleMenu = (props: WrapperProps) => {
return (
<SettingsContainer>
<Container>
<TogCon>
<Toggle toggleText={"Dark mode"} onChange={props.handleTheme}/>
</TogCon>
<TogCon>
<Toggle toggleText={"Sth"} onChange={() => {console.log("Sth")}}/>
</TogCon>
</Container>
</SettingsContainer>
);
};
Wrapper
import React, { useState } from "react";
import styled from "styled-components";
export type WrapperProps = {
children?: React.ReactNode;
color?: string;
handleTheme?: () => void;
};
const Container = styled.div<WrapperProps>`
width: 100%;
height: 100%;
top: 0;
left: 0;
position: fixed;
background-color: ${props => props.color }
`
export const Wrapper = ({ children }: WrapperProps) => {
const [theme, setTheme] = useState("black")
const handleTheme = () => {
theme === "black" ? setTheme("white"): setTheme("black")
}
return(
<Container
color={theme}
handleTheme={handleTheme}
> { children }
</Container>
);
}
Was solved with React.cloneElement
export const Wrapper = (props: WrapperProps) => {
const [theme, setTheme] = useState("black")
const handleTheme = () => {
theme === "black" ? setTheme("white"): setTheme("black")
}
const childrenWithProps = React.Children.map(props.children, child => {
if (React.isValidElement(child)) {
return React.cloneElement(child, { handleTheme });
}
return child;
});
return(
<Container color={theme} >
{ childrenWithProps }
</Container>
);
}
I'm using styled-components on my app. Styling works on home page, and all other pages except one List page. When I open this page all components (a mean tags which i created by styled-components) rendering on page, but styling not working. After I open this page, when i go to another pages which worked correctly before, styles on this pages stop working also. It's come back after page reload, but stop working again after opening List page.
here is List page code:
import React, { useEffect, useState } from 'react'
import { useLocation } from 'react-router-dom'
import styled from 'styled-components'
import {
Footer,
ListFilters,
ListProduct,
Navbar,
SearchFilterItem,
} from '../components'
const ListContainer = styled.div`
width: 100%;
`
const ListWrapper = styled.div`
min-height: 100vh;
width: 93vw;
margin: 0 auto;
padding: 30px 0px;
display: flex;
align-items: center;
opacity: ${(props) => props.o};
`
const ProductsContainer = styled.div`
flex: 5;
align-self: flex-start;
`
const ListHeader = styled.div`
display: flex;
flex-direction: column;
padding: 0px 0px 15px 20px;
`
const ListHeaderTop = styled.div`
display: flex;
justify-content: space-between;
`
const ListHeaderBottom = styled.div`
display: flex;
justify-content: flex-start;
margin-top: 10px;
padding-bottom: 10px;
`
const ListHeadeTitle = styled.h1`
font-size: 17px;
font-weight: 500;
`
const FilterBy = styled.select`
padding: 2px 5px;
width: 180px;
border: 1px solid #ccc;
color: #666;
&:focus {
outline: none;
}
`
const FilterByOption = styled.option``
const Products = styled.div`
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
padding-left: 20px;
`
const List = () => {
const location = useLocation()
const [loading, setLoading] = useState(false)
const [error, setError] = useState(false)
const [products, setProducts] = useState([])
const [filters, setFilters] = useState({
categoryFilter: [],
brandFilter: [],
sizeFilter: [],
genderFilter: [],
})
const [cat, setCat] = useState(null)
useEffect(() => {
if (location?.state?.item) {
setCat({ ...cat, category: location?.state?.item })
} else if (location?.state?.brand) {
setCat({ ...cat, brand: location?.state?.brand })
} else {
setCat(null)
}
}, [])
// console.log(location.state)
const qs =
cat &&
Object.keys(cat)
.map(
(key) =>
`${encodeURIComponent(key)}=${encodeURIComponent(cat[key])}`
)
.join('&')
useEffect(() => {
let isMounted = true
const source = axios.CancelToken.source()
const getProducts = async () => {
setLoading(true)
try {
const res = await axios.get(
cat
? `http://localhost:5000/api/products?${qs}`
: `http://localhost:5000/api/products`,
{
cancelToken: source.token,
}
)
if (isMounted) {
setProducts(res.data)
setError(null)
const allCats = [
...new Set(
res.data.map((item) => item.category).flat()
),
]
const allBrands = [
...new Set(res.data.map((item) => item.brand)),
]
const allGenders = [
...new Set(res.data.map((item) => item.gender)),
]
const allSizes = [
...new Set(res.data.map((item) => item.size).flat()),
]
setFilters({
categoryFilter: allCats,
brandFilter: allBrands,
sizeFilter: allSizes,
genderFilter: allGenders,
})
}
} catch (error) {
if (isMounted) {
setError(error.message)
setProducts(null)
}
} finally {
isMounted && setLoading(false)
}
}
getProducts()
const cleanUp = () => {
isMounted = false
source.cancel()
}
return cleanUp
}, [cat, qs])
const onToggleFilter = (categ, id) => {
if (cat && Object.entries(cat).flat().includes(id)) {
setCat(
Object.fromEntries(
Object.entries(cat).filter(([key, value]) => value !== id)
)
)
} else {
if (categ === 'gender') {
setCat({ ...cat, gender: id })
} else if (categ === 'size') {
setCat({ ...cat, size: id })
} else if (categ === 'brand') {
setCat({ ...cat, brand: id })
} else {
setCat({ ...cat, category: id })
}
}
}
const onDeleteFilter = (id) => {
// console.log(id)
setCat(
Object.fromEntries(
Object.entries(cat).filter(([key, value]) => value !== id)
)
)
}
console.log(cat)
return (
<>
<Navbar />
<ListContainer>
<ListWrapper o={loading ? 0.35 : 1}>
{/* {loading ? (
<Spinner />
) : (
<> */}
<ListFilters
cat={cat}
setCat={setCat}
filters={filters}
onToggleFilter={onToggleFilter}
/>
<ProductsContainer>
<ListHeader>
<ListHeaderTop>
<ListHeadeTitle>
{products.length} result
{products.length > 1 ? 's' : null}
{' are listed for your search'}
</ListHeadeTitle>
<FilterBy>
<FilterByOption>Sort By:</FilterByOption>
<FilterByOption value="new">
Newest Arrivals
</FilterByOption>
<FilterByOption value="low">
Price: Low
</FilterByOption>
<FilterByOption value="high">
Price: High
</FilterByOption>
</FilterBy>
</ListHeaderTop>
<ListHeaderBottom>
{cat &&
Object.keys(cat).map((key) => (
<SearchFilterItem
onDeleteFilter={onDeleteFilter}
key={key}
info={cat[key]}
/>
))}
</ListHeaderBottom>
</ListHeader>
<Products>
{products.map((item) => (
<ListProduct key={item._id} {...item} />
))}
</Products>
</ProductsContainer>
{/* </>
)} */}
</ListWrapper>
</ListContainer>
<Footer />
</>
)
}
export default List
I'm trying to add infinite scroll to my page but it's only showing me the mongo data. and while running react it's showing me a warning that says:-
"src\components\Article.jsx
React Hook useEffect has a missing dependency: 'news'. Either include it or remove the dependency array. You can also do a functional update 'setNews(n => ...)' if you only need 'news' in the 'setNews' call react-hooks/exhaustive-deps"
Article.jsx
import { useEffect , useState} from "react";
import { getNews } from "../service/api";
import InfiniteScroll from 'react-infinite-scroll-component';
import Articles from "./Articles";
const Article = () => {
const [news, setNews] = useState([]);
const [page, setPage] = useState(0);
useEffect(() => {
const dailyNews = async () => {
const response = await getNews(page);
console.log(new Set([...news, ...response.data]));
setNews([...new Set([...news, ...response.data])]);
}
dailyNews();
}, [page])
useEffect(() => {
console.log(news);
}, [news])
return(
<InfiniteScroll
dataLength={news.length *5 }
pullDownToRefreshThreshold={50}
next ={ () => setPage(page => page + 1)}
hasMore={true}
loader={<h4>Loading...</h4>}>
{
news.map(article =>(
<Articles article={article} />
))
}
</InfiniteScroll >
)
}
export default Article;
and Articles.jsx
import { Card, CardContent, Typography, styled, Grid } from "#mui/material";
const Component = styled(Card)`
box-shadow: 0 2px 5px 0 rgb(0 0 0 / 16%), 0 2px 10px 0 rgb(0 0 0 / 12%);
margin-bottom: 20px;
`;
const Container = styled(CardContent) `
display: flex;
padding: 8px;
padding-bottom: 4px !important;
`;
const Image = styled('img')({
height: 268,
width: '88%',
borderRadius: 5,
objectFit: 'cover'
});
const RightContainer = styled(Grid)(({ theme }) => ({
margin: '5px 0px 0 -25px',
display: 'flex',
flexDirection: 'column',
[theme.breakpoints.between('sm', 'lg')]: {
padding: '0 5px'
},
[theme.breakpoints.down('sm')]: {
margin: '5px 0'
}
}));
const Title = styled(Typography)`
font-weight: 300;
color: #44444d;
font-size: 22px;
line-height: 27px;
`;
const Author = styled(Typography)`
color: #808290;
font-size: 12px;
line-height: 22px;
`;
const Description = styled(Typography)`
line-height: 22px;
color: #44444d;
margin-top: 5px;
font-family: 'Roboto',sans-serif;
font-weight: 300;
`;
const Short = styled('b')({
color: '#44444d',
fontFamily: "'Convergence', sans-serif"
})
const Publisher = styled(Typography)`
font-size: 12px;
margin-top: auto;
margin-bottom: 10px;
'& > *': {
textDecoration: 'none',
color: '#000',
fontWeight: 900
}
`;
const Articles = ({ article }) => {
return (
<Component>
<Container>
<Grid container>
<Grid lg={5} md={5} sm={5} xs={12} item>
<Image src={article.url} />
</Grid>
<RightContainer lg={7} md={7} sm={7} xs={12} item>
<Title>{article.title}</Title>
<Author>
<Short>short</Short> by {article.author} / {new Date(article.timestamp).toDateString()}
</Author>
<Description>{article.description}</Description>
<Publisher>
read more at {article.publisher}
</Publisher>
</RightContainer>
</Grid>
</Container>
</Component>
)
}
export default Articles;
Try to write like this
useEffect(() => {
const dailyNews = async () => {
const response = await getNews(page);
console.log(new Set([...news, ...response.data]));
setNews([...new Set([...news, ...response.data])]);
}
dailyNews();
//eslint-disable-next-line
}, [page])
Please please help me in adding infinite scroll to my page
I'm using "react-infinite-scroll-component" npm package
Use following format for all useEffect hook
useEffect(()=> {
...
//eslint-disable-next-line
},[])
You can put
// eslint-disable-next-line react-hooks/exhaustive-deps
before the violating line if there is a good reason.
Read react team member comment
Write useEffect like this
useEffect(() => {
const dailyNews = async () => {
const response = await getNews(page);
console.log(new Set([...news, ...response.data]));
setNews([...new Set([...news, ...response.data])]);
}
dailyNews();
// eslint-disable-next-line
}, [page])
or you can add missing dependencies there like this
useEffect(() => {
const dailyNews = async () => {
const response = await getNews(page);
console.log(new Set([...news, ...response.data]));
setNews([...new Set([...news, ...response.data])]);
}
dailyNews();
}, [page, news, setNews])
I have the following code in signin.js and I am using Axios API to integrate it with the code so that it redirects to the dashboard. I have the following URL for API (https://9d6e-110-44-127-177.ngrok.io/auth/login/) and email that is verified is "m#m.com" and password is admin#123 but I don't know how to integrate with the code. The code for signin.jsx is as below:
signin.jsx
import React, {useState} from 'react'
import styled from 'styled-components'
import StyledInput from './StyledInput'
import StyledButton from './StyledButton'
import { Link } from 'react-router-dom'
import './Signin.css'
import axios from 'axios'
const Container = styled.div`
display: flex;
flex-direction: column;
justify-content:center;
align-items: center;
height: 80vh;
width: 30vw;
background: #E8E8E8;
`;
const Welcome = styled.h2`
margin: 3rem 0 2rem 0;
box-sizing: border-box;
background-color: #00009c;
border: 2px solid #00009c;
border-radius: 2rem;
padding: 15px;
text-transform: uppercase;
color: white;
letter-spacing: 0.4rem;
`;
const Form = styled.form`
width: 100%;
height: 100vh;
justify-content: center;
align-items: flex-start;
`;
const Input = styled.div`
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
height:20%;
width: 100%;
` ;
const Button = styled.div`
margin: 1rem 0 2rem 0;
width: 90%;
display: flex;
align-items: center;
justify-content: center;
`;
const Paragraph = styled.p`
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
`;
const Check = styled.input`
font-size: 15px;
margin-left: -400px;
box-sizing: border-box;
`;
const Label = styled.label`
margin-top: -120px;
margin-left: -270px;
`;
const Signin = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = (e) => {
e.preventDefault()
axios.post("https://9d6e-110-44-127-177.ngrok.io/auth/login/", {
email: "m#m.com",
password: "admin#123"
})
.await((response) => {
console.log(response)
})
.catch((err) => {
console.log(err)
alert(err.response.data.error.message)
})
}
const handleEmail = (e) => {
setEmail(e.target.value)
}
const handlePassword = (e) => {
setPassword(e.target.value)
}
return (
<Container>
<Welcome>
Welcome
</Welcome>
<Form onSubmit= {handleSubmit}>
<Input>
<StyledInput type="email"
placeholder="Email"
required
value={email}
onChange = {handleEmail}
/>
</Input>
<Input>
<StyledInput type="password"
placeholder="Password"
required
value={password}
onChange = {handlePassword} />
</Input>
<Input>
<Check type="checkbox" />
<Label>Remember me</Label>
</Input>
<Link to = "dashboard">
<Button onLink = {handleSubmit}>
<StyledButton content = "Log in" />
</Button>
</Link>
<Paragraph>
Don't have an account?
<Link to = "register">Sign up</Link>
</Paragraph>
</Form>
</Container>
);
}
export default Signin
I also want to use async await in the sign in.
How can that be done?
.await((response) => { // not await, it should be then
console.log(response)
})
should be "then" instead
.then((response) => {
console.log(response)
})
Here is how you use async await which is more readable.
const handleSubmit = async (e) => {
e.preventDefault()
try {
let response = await axios.post(
"https://9d6e-110-44-127-177.ngrok.io/auth/login/",
{
email: "m#m.com",
password: "admin#123",
}
);
console.log(response);
} catch (error) {
console.error(error);
}
};
import React, {useState} from 'react'
import styled from 'styled-components'
import StyledInput from './StyledInput'
import StyledButton from './StyledButton'
import { Link } from 'react-router-dom'
import './Signin.css'
import axios from 'axios'
const Signin = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleSubmit = async () => {
e.preventDefault()
await axios.post("https://9d6e-110-44-127-177.ngrok.io/auth/login/", {
email : email,
password : password
}).then((res) => {
if(res.data.email === "m#m.com" && res.data.password === "admin#123")
}).catch((err) => {
console.log(err) ;
})
}
const handleEmail = (e) => {
setEmail(e.target.value)
}
const handlePassword = (e) => {
setPassword(e.target.value)
}
return (
<Container>
<Welcome>
Welcome
</Welcome>
<Form onSubmit= {handleSubmit}>
<Input>
<StyledInput type="email"
placeholder="Email"
required
value={email}
onChange = {handleEmail}
/>
</Input>
<Input>
<StyledInput type="password"
placeholder="Password"
required
value={password}
onChange = {handlePassword} />
</Input>
<Input>
<Check type="checkbox" />
<Label>Remember me</Label>
</Input>
<Link to = "dashboard">
<Button onLink = {handleSubmit}>
<StyledButton content = "Log in" />
</Button>
</Link>
<Paragraph>
Don't have an account?
<Link to = "register">Sign up</Link>
</Paragraph>
</Form>
</Container>
);
}
export default Signin
Please I needed to add a button before the previousLabel property details and after the nextLabel prop details in React-Paginate but what I have below is not working. I have also tried to read the documentation and check all the prop details but still couldn't achieve the result below.
I want a first button to come before one button and a last button to come after the next button.
what the code below looks like above.
what I want to achieve below
```
import React, { useState, useEffect } from 'react'
import axios from 'axios'
import ReactPaginate from 'react-paginate';
import './styles.css'
export default function App() {
const [postsPerPage] = useState(5);
const [offset, setOffset] = useState(1);
const [posts, setAllPosts] = useState([]);
const [pageCount, setPageCount] = useState(0)
const getPostData = (data) => {
return (
data.map(post => <div className="container" key={post.id}>
<p>User ID: {post.id}</p>
<p>Title: {post.title}</p>
</div>)
)
}
const getAllPosts = async () => {
const res = await axios.get(`https://jsonplaceholder.typicode.com/posts`)
const data = res.data;
const slice = data.slice(offset - 1 , offset - 1 + postsPerPage)
// For displaying Data
const postData = getPostData(slice)
// Using Hooks to set value
setAllPosts(postData)
setPageCount(Math.ceil(data.length / postsPerPage))
}
const handlePageClick = (event) => {
const selectedPage = event.selected;
setOffset(selectedPage + 1)
};
useEffect(() => {
getAllPosts()
}, [offset])
return (
<div className="main-app">
{/* Display all the posts */}
{posts}
{/* Using React Paginate */}
<ReactPaginate
previousLabel={"previous"}
nextLabel={"next"}
breakLabel={"..."}
breakClassName={"break-me"}
pageCount={pageCount}
onPageChange={handlePageClick}
containerClassName={"pagination"}
subContainerClassName={"pages pagination"}
activeClassName={"active"} />
</div>
);
}
```
Below is the css
.main-app {
margin: 2% 10%;
border: 1px ridge #464141;
padding: 5%;
font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
font-size: 20px;
color: #464141;
}
.container {
border-bottom: #fff 2px ridge;
}
.pagination {
margin-top: 45px;
margin-left: -40px;
display: flex;
list-style: none;
outline: none;
}
.pagination>.active>a {
background-color: #47ccde;
color: #fff;
}
.pagination>li>a {
border: 1px solid #47ccde;
padding: 5px 10px;
outline: none;
cursor: pointer;
}
.pagination>li>a, .pagination>li>span {
color: #47ccde;
background-color: azure;
}