Adding A button before the previousLabel Props and after the nextLabel Props in React-Paginate Not Working - reactjs

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;
}

Related

How can I show the uploaded image in React?

I'm going to upload an image with react now. When I selected the image and received the value of the selected image in state, I got an array like below. But how do I approach this array to see this selected image? If you look at the picture, there is no path to the picture in the array, so I want to know which value to choose to see the picture. I'd appreciate it if you let me know, thanks.
import React from 'react'
import { useState } from 'react';
import styled from 'styled-components';
function MakeModal() {
const fileInput = React.useRef(null);
const [isfile,setIsfile] = useState("");
const handleButtonClick = e => {
fileInput.current.click();
};
const handleChange = e => {
setIsfile(e.target.files[0]);
console.log(e.target.files[0]);
};
const objectUrl = URL.createObjectURL(isfile);
console.log('check',objectUrl)
return (
<Modal>
<div>
<div>
<div>
<div>
<input
type="file"
style={{display:'none'}}
ref={fileInput}
onChange={handleChange}
multiple={true}/>
<button
className='box9_2_3_3_2'
onClick={handleButtonClick}>
choose img
</button>
</div>
</div>
</div>
</div>
</Modal>
)
}
export default MakeModal;
const Modal = styled.div`
display: ${props=>props.isModal===true?'block':'none'};
position: fixed;
background-color: rgba(0,0,0,0.65);
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 500343;
.box9_2_3_3_2 {
background-color: rgb(0,149,246)!important;
border: 1px solid transparent;
border-radius: 4px;
color: white;
position: relative;
-webkit-appearance: none;
background: none;
box-sizing: border-box;
cursor: pointer;
display: block;
}
`
You only need to create an ObjectUrl from your file like this :
const objectUrl = URL.createObjectURL(file); // or file[0] if it's an array
...
<img src={objectUrl} ... />
...
A good practise is to revoke the URL when the compenent unmount, or when the file change. One exemple is to do it like this, it depends on your logic :
const [isFile, setIsFile] = useState('');
const [preview, setPreview] = useState('');
useEffect(() => {
if (isFile) {
const objectUrl = URL.createObjectURL(isFile); // create here
setPreview(objectUrl);
}
return () => URL.revokeObjectURL(isFile); // And revoke on unmount
}, [isFile]); // or whatever you called the variable you put the file in
return (
...
<img src={preview} ... />
...
)

handling events on custom components

I have these files:
button.module.css
.base {
display: flex;
font-size: 16px;
font-family: "Helvetica Neue";
align-items: center;
justify-content: center;
padding: 6px 12px 6px 12px;
width: 50px;
border-radius: 6px;
}
.normal {
composes: base;
color:black;
background-color: #aeeeb7;
border: 1px solid #42924d;;
}
.danger {
composes: base;
color:black;
background-color: rgb(253, 128, 128);
border: 1px solid rgb(196, 108, 108);
}
button.js
import classes from './button.module.css';
const ButtonTypes = {
'normal': classes.normal,
'danger': classes.danger
};
const Button = (props) => {
const className = ButtonTypes[props.type] ? ButtonTypes[props.type] : classes.normal;
return <div role="button" className={className} ...props>{text}</div>;
}
export default Button;
app.js
import Button from './button';
const App = () => {
const handleClick = () => {
console.log('app');
}
const handleMouseOver = () => {
console.log('mouse-over');
}
...
return (
<div>
<Button type="normal" onClick=(handleClick) onMouseOver={handleMouseOver} ...>
</div>
);
}
export default Button;
I am changing the class of the button depending on the "type" property. (It could be other components not just a button)
How should I handle events on the custom component? Is the way I am passing them right now to that div inside fine or I should do it differently?
I want to create some custom components and I am trying to verify I am doing it the right way.
One suggestion here. Instead of spreading all props in button. You can destructure out the required props and then spread the rest props.
import classes from "./button.module.css";
const ButtonTypes = {
normal: classes.normal,
danger: classes.danger
};
const Button = ({ type, ...rest }) => {
const className = ButtonTypes[type] ? ButtonTypes[type] : classes.normal;
return (
<div role="button" className={className} {...rest}>
{text}
</div>
);
};
export default Button;

eact Hook useEffect has a missing dependency: ' xyz '. Either include it or remove the dependency array

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])

Values getting undefined when consuming data using useContext in the child component

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>

React Context API returns undefined

I'm quite new to React, and i'm trying to make a ToDoList. I have a Modal with a submit button that when pressed should add a ToDoItem. But since i didn't want to prop drill my way through this i wanted to use the Context API. The Context API confuses me quite a bit, maybe i'm just a moron, but i have a hard time understanding why i have to make a hook and pass that as the value in the provider. I thought that in the ToDoContext that i already defined the default value as a empty array, so i just did it again.
In the console at line 62, which is my initial render it says that it's undefined, after the pressing the Add ToDo I get the same message.
App.jsx
import React, { useState } from "react";
import { render } from "react-dom";
import { ThemeProvider } from "emotion-theming";
import { defaultTheme } from "./theme";
import { Global, css } from "#emotion/core";
import Header from "./components/Header";
import ToDoList from "./components/ToDoList";
import AddBtn from "./components/AddBtn";
import ToDoContext from "./ToDoContext";
const App = () => {
const [toDoItems] = useState([]);
return (
<>
{/*Global styling*/}
<Global
styles={css`
* {
margin: 0;
padding: 0;
box-sizing: border-box;
list-style: none;
text-decoration: none;
}
`}
/>
{/*App render start from here*/}
<ThemeProvider theme={defaultTheme}>
<ToDoContext.Provider value={toDoItems}>
<Header />
<main>
<ToDoList />
<AddBtn />
</main>
</ToDoContext.Provider>
</ThemeProvider>
</>
);
};
render(<App />, document.getElementById("root"));
ToDoContext.jsx
import { createContext } from "react";
const ToDoContext = createContext([[], () => {}]);
export default ToDoContext;
AddBtn.jsx
import React, { useState, useContext } from "react";
import { css } from "emotion";
import Modal from "../Modal";
import ToDoContext from "../ToDoContext";
const BtnStyle = css`
position: fixed;
bottom: 0;
right: 0;
cursor: pointer;
display: block;
font-size: 7rem;
`;
const ModalDiv = css`
position: fixed;
left: 50%;
background-color: #e6e6e6;
width: 60%;
padding: 20px 20px 100px 20px;
display: flex;
flex-direction: column;
align-items: center;
max-width: 400px;
height: 50%;
transform: translate(-50%, -50%);
border-radius: 20px;
top: 50%;
`;
const textareaStyle = css`
resize: none;
width: 100%;
height: 200px;
font-size: 1.25rem;
padding: 5px 10px;
`;
const timeStyle = css`
font-size: 3rem;
display: block;
`;
const modalSubmit = css`
width: 100%;
font-size: 3rem;
cursor: pointer;
margin-top: auto;
`;
const Label = css`
font-size: 2rem;
text-align: center;
display: inline-block;
margin-bottom: 50px;
`;
const AddBtn = () => {
const [showModal, setShowModal] = useState(true);
const [time, setTime] = useState("01:00");
const [toDoItems, setToDoItems] = useContext(ToDoContext);
console.log(toDoItems);
return (
<>
<div className={BtnStyle} onClick={() => setShowModal(!showModal)}>
<ion-icon name="add-circle-outline"></ion-icon>
</div>
{showModal ? (
<Modal>
<div className={ModalDiv}>
<div>
<label className={Label} htmlFor="time">
Time
<input
className={timeStyle}
type="time"
name="time"
value={time}
onChange={(e) => setTime(e.target.value)}
/>
</label>
</div>
<label className={Label} htmlFor="desc">
Description
<textarea
className={textareaStyle}
name="desc"
placeholder={`Notify yourself this message in ${time}`}
></textarea>
</label>
<button
className={modalSubmit}
onClick={() => {
setToDoItems(
toDoItems.push({
time,
})
);
}}
>
Add ToDo
</button>
</div>
</Modal>
) : null}
</>
);
};
export default AddBtn;
There are few issues in your code to fix:
useState returns a value and a setter. With this line of code, const [toDoItems] = useState([]);, you are just passing an empty array to your context.
So do this:
const toDoItems = useState([]);
In your ToDoContext.js, just pass an empty array as argument (initial value)
const ToDoContext = createContext([]);
Working copy of your code is here. (see console logs)
Also, I noticed that you are pushing the todo in setTodoItems in AddBtn.js.
Don't do this:
onClick={() => {
setToDoItems(
toDoItems.push({
time
})
);
}}
Do this:
onClick={() => {
setToDoItems(
toDoItems.concat([
{
time
}
])
);
}}

Resources