How do I open my react-modal through a component? - reactjs

I have a component that is a modal for login, but I'm not able to call it this is the code of the component:
import React from 'react';
import ReactDOM from 'react-dom';
import Modal from 'react-modal';
const INITIAL_USER = {
email: '',
password: ''
}
const ModalLogin = () => {
const [user, setUser] = React.useState(INITIAL_USER);
const [disabled, setDisabled] = React.useState(true);
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState('');
const [modalIsOpen, setIsOpen] = React.useState(false);
function openModal() {
setIsOpen(true);
}
function closeModal() {
setIsOpen(false);
}
React.useEffect((modal) => {
const isUser = Object.values(user).every(el => Boolean(el));
isUser ? setDisabled(false) : setDisabled(true)
}, [user]);
const handleChange = (e) => {
const { name, value } = e.target;
setUser(prevState => ({ ...prevState, [name]: value }));
}
const handleSubmit = async e => {
e.preventDefault();
try {
setLoading(true);
setError('');
const url = `${baseUrl}/api/login`;
const payload = { ...user };
const response = await axios.post(url, payload);
handleLogin(response.data);
} catch (error) {
catchErrors(error, setError);
} finally {
setLoading(false);
}
}
const customStyles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)'
}
};
return (
<Modal
isOpen={modalIsOpen}
style={customStyles}
onRequestClose={closeModal}
>
<div className="theme_login">
<div className="theme_login_box radius">
<header>
<h1>Fazer Login:</h1>
<p>Informe seu nome e e-mail para fazer login e acessar seus pedidos.</p>
</header>
<form method="POST" onSubmit={handleSubmit}>
<input className="radius" type="email" name="email" value={user.email} onChange={handleChange} placeholder="E-mail:" />
<input className="radius" type="password" name="password" value={user.password} onChange={handleChange} placeholder="Senha:" />
<button className="btn transition radius icon-success" type="submit" href="/" title="Minha conta">Fazer Login</button>
</form>
Esqueci minha senha
</div>
</div>
</Modal>
)
};
export default ModalLogin;
I want to call him through my StaticHeader.js:
import React from 'react';
import Link from "next/link";
import Router, { useRouter } from 'next/router';
import NProgress from 'nprogress';
import { handleLogout } from '../../utils/auth';
import ModalLogin from './ModalLogin';
import ReactDOM from 'react-dom';
import Modal from 'react-modal';
Router.onRouteChangeStart = () => NProgress.start();
Router.onRouteChangeComplete = () => NProgress.done();
Router.onRouteChangeError = () => NProgress.done();
const StaticHeader = ({ user }) => {
const router = useRouter();
const [menuActive, setMenuActive] = React.useState(false);
const [search, setSearch] = React.useState({ search: '' });
//console.log(user)
const isRoot = user && user.role == 'root';
const isAdmin = user && user.role == 'admin';
const isRootOrAdmin = isRoot || isAdmin;
const [modalIsOpen, setIsOpen] = React.useState(false);
function openModal() {
setIsOpen(true);
}
function closeModal() {
setIsOpen(false);
}
const isActive = (route) => {
return route == router.pathname;
}
const handleOnChange = (e) => {
const { name, value } = e.target;
setSearch(prevState => ({ ...prevState, [name]: value }))
}
const handleSearch = (e) => {
Router.push({
pathname: '/products',
query: { term: search.search }
})
}
const menuToggle = () => {
setMenuActive(!menuActive)
}
const customStyles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)'
}
};
return (
<header className="main_header">
<div className="container">
<div className="main_header_nav">
<div className="main_header_nav_logo">
<a href="" title="WdpShoes | Home">
<img alt="logo" title="logo menu" src="/css/themes/logo/wdpshoes_logo_white.png" />
</a>
</div>
<div className="main_header_nav_search">
<form action="" method="post" className="radius">
<input type="text" name="s" placeholder="Pesquisar na loja:" />
<button className="icon-search icon-notext transition"></button>
</form>
</div>
<div className="main_header_nav_menu">
<a className="icon-cart icon-notext transition main_header_nav_menu_cart" href="/cart"><span>3</span></a>
<div className="main_header_nav_menu_user">
<a href="#" title="#" className="icon-user main_header_nav_menu_user_a radius transition" onClick={openModal} >
{modalIsOpen && <ModalLogin/>}
Login</a>
<nav className="radius">
Meus Pedidos
Meus Pedeidos
Meus endereços
Sair
</nav>
</div>
</div>
</div>
<ul className="main_header_departments">
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_deprtaments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
</ul>
</div>
</header>
);
}
export default StaticHeader;
What do I need to do for this modal to appear in my header when clicking on login?
I believe it will be necessary to send the functions through the props I tried a few times without success please could someone help solve this problem?

Related

how to add data in localstorage in react

I am arslan Chaudhry. currently, I am working on an eCommerce site where I will store data in local storage because I don't have too much backend knowledge. how I can add functionality like delete and update on another folder.
my code is given below.
Books.js
import React from "react";
import "./components/book.css";
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";
import { FaShoppingCart } from "react-icons/fa";
import { useEffect } from "react";
import { useState, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { createContext } from "react";
const Books = () => {
let arr=()=>{
let dat=localStorage.getItem("products")
if (dat) {
return JSON.parse(dat)
}
else{
return []
}
}
const [booksData, setbooksData] = useState([]);
const [productData, setproductData] = useState(arr());
let nav = useNavigate();
// slider
const responsive = {
superLargeDesktop: {
breakpoint: { max: 4000, min: 3000 },
items: 5,
},
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3,
},
tablet: {
breakpoint: { max: 1024, min: 464 },
items: 2,
},
mobile: {
breakpoint: { max: 464, min: 0 },
items: 1,
},
};
let croser = useRef("");
let loding = useRef("");
const getJason = async () => {
try {
let fea = await fetch(
"https://script.google.com/macros/s/AKfycbxFCG7S-kjncQZwvcMnqq4wXoBAX8ecH1zkY2bLP7EE-YHlnKbiJ3RUuHtWLe6sIK30Kw/exec"
);
let acData = await fea.json();
let itemsData = acData.shop.filter((element) => {
if (element.name) {
return element;
}
});
setbooksData(itemsData);
if (itemsData) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
} catch (error) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
};
// get product data from api
useEffect(() => {
getJason();
}, []);
// go to cart button
const goto = () => {
nav("/Cart");
};
// local data
let addNow=(e)=>{
let data=productData.find((element)=>{return element.id === e.id });
let cart;
if (data) {
cart=productData.map((element)=>{
return element.id === e.id ? {...element, quantity:element.quantity+1}:element
})
}
else{
cart=[...productData,{...e, quantity:1}]
}
setproductData(cart);
};
useEffect(() => {
localStorage.setItem("products",JSON.stringify(productData))
}, [productData])
console.log(productData);
return (
<>
<div className="row " style={{ marginTop: "10px" }}>
<div className="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div className="section-headline text-center">
<h2>Books Shop</h2>
</div>
</div>
</div>
<div className="lodingBooks" ref={loding}>
<div class="spinner-border" role="status"></div>
<h4>Please wait....</h4>
</div>
<div ref={croser}>
<div className=" shadow go_to_cart" onClick={goto}>
<i class="bi bi-cart-check text-white"></i>
</div>
<Carousel responsive={responsive} className="container">
{booksData.map((element) => {
return (
<>
<div class="container page-wrapper">
<div class="page-inner">
<div class="row">
<div class="el-wrapper">
<div class="box-up">
<img class="img" src={element.images} alt="" />
<div class="img-info">
<div class="info-inner">
<span class="p-name text-info">
{element.name}
</span>
<span class="p-company ">Author:CHAUDHRY</span>
</div>
<div class="a-size ">
About:This is a complete book on javascript
<span class="size"></span>
</div>
</div>
</div>
<input
type="text"
value={1}
style={{ display: "none" }}
/>
<div class="box-down">
<div class="h-bg">
<div class="h-bg-inner"></div>
</div>
<a class="cart">
<span class="price">{element.price + "$"}</span>
<span
class="add-to-cart btn btn-sm"
style={{ backgroundColor: "#3EC1D5" }}
onClick={()=>{addNow(element)}}
>
<span class="txt">
ADD TO CART <FaShoppingCart />
</span>
</span>
</a>
</div>
</div>
</div>
</div>
</div>
</>
);
})}
</Carousel>
</div>
</>
);
};
export default Books;
and here is my cart file. where i want to perform the action like update and delete.
Cart.js
import React from "react";
import "./components/cart.css";
import { useEffect } from "react";
const Cart = () => {
let data = localStorage.getItem("products");
let javaData = JSON.parse(data);
let removeData = (e) => {
};
useEffect(() => {
localStorage.clear()
}, [])
return (
<>
<div class="container mt-5 mb-5">
<div class="d-flex justify-content-center row">
<div class="col-md-8">
<div class="p-2 shoingTitle">
<h4>Shop Now</h4>
<span class="text-danger">Remove all</span>
</div>
{javaData ? (
javaData.map((item) => {
return (
<>
<div class="d-flex flex-row justify-content-between align-items-center p-2 bg-white mt-4 px-3 rounded">
<div class="mr-1 imageandpara">
<img class="rounded" src={item.images} width="70" />
<span class="font-weight-bold">{item.name}</span>
</div>
<div class="d-flex flex-column align-items-center product-details">
<div class="d-flex flex-row product-desc"></div>
</div>
<div class="d-flex flex-row align-items-center qty">
<i class="minusSign shadow">
<i class="bi bi-dash"></i>
</i>
<span class="text-grey quantityNumber">
{item.quantity}
</span>
<i class="minusSign shadow">
<i class="bi bi-plus"></i>
</i>
</div>
<div>
<span class="text-grey productAmount">{`${
item.quantity * item.price
}$`}</span>
</div>
<div
class="d-flex align-items-center text-dark "
style={{
cursor: "pointer",
fontWeight: "900",
fontSize: "15px",
}}
onClick={() => {
removeData(item);
}}
>
<i class="bi bi-x text-danger"></i>
</div>
</div>
</>
);
})
) : (
<h3 style={{ textAlign: "center" }}>Cart is empety</h3>
)}
<div class="d-flex flex-row align-items-center mt-3 p-2 bg-white rounded">
<input
type="text"
class="form-control gift-card "
placeholder="discount code/gift card"
/>
<button
class="btn btn-sm ml-3 shadow"
type="button"
style={{
outline: "#3EC1D5",
backgroundColor: "#3EC1D5",
color: "white",
}}
>
Apply
</button>
</div>
<div class="totalItems">
Total Items: <strong>12</strong>
</div>
<span class="TotalPrice">
Total price: <strong>12$</strong>
</span>
<div class="d-flex flex-row align-items-center mt-3 p-2 bg-white rounded">
<button
class="btn btn-block btn-sm ml-2 pay-button shadow"
type="button"
style={{ backgroundColor: "#3EC1D5" }}
>
Proceed to Pay
</button>
</div>
</div>
</div>
</div>
</>
);
};
export default Cart;
Try this for add:
let removeData = (e) => {
localStorage.setItem("name of the item") // e.target.name
};
There's alot going on in your site :)
I think it will be responsible to create a context, that will serve the cart to all other components.
Things to note here, (Found some little improvements)
Run the function in the useState hook, don't just leave it there like you did
When using Array.filter you need to return a boolean iorder for it too filter your array properly.
This is the code I brought up hope it helps you out.
CartContext.js file.
import React, { createContext, useContext, useEffect, useState } from "react";
export const CartContext = createContext();
function Cart({ children }) {
const arr = useCallback(() => {
let dat = localStorage.getItem("products");
if (dat) {
return JSON.parse(dat);
} else {
return [];
}
}, []);
const [productData, setproductData] = useState(() => arr());
const getJason = async () => {
try {
let fea = await fetch(
"https://script.google.com/macros/s/AKfycbxFCG7S-kjncQZwvcMnqq4wXoBAX8ecH1zkY2bLP7EE-YHlnKbiJ3RUuHtWLe6sIK30Kw/exec"
);
let acData = await fea.json();
// filter callback function should return a boolean. That is either true or false in order to make it work.
// SO i think this function isn't going to function properly
let itemsData = acData.shop.filter((element) => {
if (element.name) {
return element;
}
});
setbooksData(itemsData);
if (itemsData) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
} catch (error) {
croser.current.style.filter = "blur(0px)";
loding.current.style.display = "none";
}
};
// get product data from api
useEffect(() => {
getJason();
}, []);
const addProduct = (e) => {
// check if product id available on cart
const findProduct = productData.find((element) => {
return element.id === e.id;
});
// add first quantity if not available
if (!findProduct)
return setproductData([...productData, { ...e, quantity: 1 }]);
// increase quantity by 1
const newCart = productData.map((element) => {
return {
...element,
quantity: element.id === e.id ? element.quantity + 1 : element.quantity,
};
});
setproductData(newCart);
};
const removeProduct = (e) => {
// check if product id available on cart
const findProductQuantity = productData.find((element) => {
return element.id === e.id && element.quantity >= 1;
});
// add first quantity if not available
if (!findProduct)
// Your ui should prevent this
return;
// decrease quantity by 1
const reducedQuantityCart = productData.map((element) => {
return {
...element,
quantity: element.id === e.id ? element.quantity - 1 : element.quantity,
};
});
// filter out all products with quantity less than 1 (quantity : 0)
const newCart = productData.filter((element) => {
return element.quantity >= 1;
});
setproductData(newCart);
};
const deleteProduct = (e) => {
// check if product id available on cart
const findProduct = productData.find((element) => {
return element.id === e.id;
});
// add first quantity if not available
if (!findProduct)
// Your ui should prevent this
return;
const productIndex = productData.findIndex((element) => {
return element.id === e.id;
});
// splice (delete) product from the productData array
const newCart = [productData].splice(productIndex, 1);
setproductData(newCart);
};
const value = {
productData,
addProduct,
removeProduct,
deleteProduct,
};
return <CartContext.Provider value={value}>{children}</CartContext.Provider>;
}
In here you create a context, create all your function you will use to update your cart, and pass them to your Context provider
// create a hook can you use anywhere in the app
export const useCart = () => {
const context = useContext(CartContext);
if (!context) {
throw new Error("Must use useCart in CartContext Child");
}
const { productData, addProduct, removeProduct, deleteProduct } = context;
return { productData, addProduct, removeProduct, deleteProduct };
};
For this you create a custom hook that you can use inside any component provided it is a child of the Cart context. So make sure you wrap it all around your app
// Use Case
const SomeComponent = () => {
const { productData, addProduct, removeProduct } = useCart();
return (
<div>
<p> Number of Products: {productData.length}</p>
<div>
{productData?.map((product) => (
<div>
<p>{product?.name}</p>
<button onClick={() => addProduct(product)}>add</button>
<button onClick={() => removeProduct(product)}>
subtract/reduce
</button>
<button onClick={() => deleteProduct(product)}>delete</button>
</div>
))}
</div>
</div>
);
};
Use case Scenario od how this code will work. Hope you find this helful

React parent component needs child function to return data

I think I need a call back function, but do not understand the proper syntax given a parent component calling a child function.
Here is the stripped down parent component followed by the function FilesUpload.
I need the File.Name from child returned and setState({fileName}) in parent component.
Hopefully painfully obvious to someone who knows how to do this.
Thank you in advance for solution.
Rob
#davidsz - any ideas?
...
//Stripped down ParentComponent.jsx
import React, { Component } from 'react'
import FilesUpload from "../Services/FilesUpload";
class ParentComponent extends Component {
constructor(props) {
super(props)
this.state = {
fileName: null
}
this.changefileNameHandler = this.changefileNameHandler.bind(this);
}
changefileNameHandler= (event) => {
this.setState({fileName: event.target.value});
}
componentDidMount(){
}
render() {
return (
<div>
<td>this.state.fileName </td>
<FilesUpload onUpdate={this.changefileNameHandler}/>
</div>
)
}
}
export default ParentComponent
//functional service FilesUpload.js
import React, { useState, useEffect, useRef } from "react";
import UploadService from "../Services/FileUploadService";
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
const UploadFiles = () => {
const [selectedFiles, setSelectedFiles] = useState(undefined);
const [progressInfos, setProgressInfos] = useState({ val: [] });
const [message, setMessage] = useState([]);
const [fileInfos, setFileInfos] = useState([]);
const progressInfosRef = useRef(null)
useEffect(() => {
UploadService.getFiles().then((response) => {
setFileInfos(response.data);
});
}, []);
const selectFiles = (event) => {
setSelectedFiles(event.target.files);
setProgressInfos({ val: [] });
};
const upload = (idx, file) => {
let _progressInfos = [...progressInfosRef.current.val];
return UploadService.upload(file, (event) => {
_progressInfos[idx].percentage = Math.round(
(100 * event.loaded) / event.total
);
setProgressInfos({ val: _progressInfos });
})
.then(() => {
toast.info(file.name + " Uploaded")
setMessage((prevMessage) => ([
...prevMessage,
"Uploaded the file successfully: " + file.name,
]));
})
.catch(() => {
_progressInfos[idx].percentage = 0;
setProgressInfos({ val: _progressInfos });
setMessage((prevMessage) => ([
...prevMessage,
"Could not upload the file: " + file.name,
]));
});
};
const uploadFiles = () => {
const files = Array.from(selectedFiles);
let _progressInfos = files.map(file => ({ percentage: 0, fileName: file.name }));
progressInfosRef.current = {
val: _progressInfos,
}
const uploadPromises = files.map((file, i) => upload(i, file));
Promise.all(uploadPromises)
.then(() => UploadService.getFiles())
.then((files) => {
setFileInfos(files.data);
});
setMessage([]);
};
return (
<div>
{progressInfos && progressInfos.val.length > 0 &&
progressInfos.val.map((progressInfo, index) => (
<div className="mb-2" key={index}>
<span>{progressInfo.fileName}</span>
<div className="progress">
<div
className="progress-bar progress-bar-info"
role="progressbar"
aria-valuenow={progressInfo.percentage}
aria-valuemin="0"
aria-valuemax="100"
style={{ width: progressInfo.percentage + "%" }}
>
{progressInfo.percentage}%
</div>
</div>
</div>
))}
<div className="row my-3">
<div className="col-8">
<label className="btn btn-default p-0">
<input type="file" multiple onChange={selectFiles} />
</label>
</div>
<div className="col-4">
<button
className="btn btn-success btn-sm"
disabled={!selectedFiles}
onClick={uploadFiles}
>
Upload
</button>
</div>
</div>
{message.length > 0 && (
<div className="alert alert-secondary" role="alert">
<ul>
{message.map((item, i) => {
return <li key={i}>{item}</li>;
})}
</ul>
</div>
)}
<div className="card">
{/* <div className="card-header">List of Files</div> */}
<ul className="list-group list-group-flush">
{!fileInfos &&
fileInfos.map((file, index) => (
<li className="list-group-item" key={index}>
{/* <a href={file.url}>{file.name}</a> */}
</li>
))}
</ul>
</div>
<ToastContainer position="top-center" autoClose={1000}/>
</div>
);
};
export default UploadFiles;
...
I'm not quite sure I understand your question perfectly, but do you want to pass down the changefileNameHandler function as a prop to your FilesUpload functional component?
In this case you can just add props as a paremeter:
const UploadFiles = (props) => { ...
and call it wherever you need it:
props.onUpdate(event)

react add search functionality alongside categories

import axios from 'axios'
import React from 'react'
import { useState, useEffect } from 'react'
import {useHistory} from 'react-router-dom'
import Spinner from './Spinner'
const Home = () => {
const [search, setSearch] = useState({
category: 'All',
searchBar: '',
})
const handleCategory = e => {
setSearch({...search, category: e.target.id})
}
const handleSearch = e => {
setSearch({...search, searchBar: e.target.value})
}
// This only works for the categories
const filteredPreviews = search.category === 'All'
? previews
: previews.filter(preview => preview.category === search.category)
return (
<div className="container">
<section className="main-nav">
<div className="main-nav-content">
<ul className='categories'>
<li><a onClick={(e) => handleCategory(e)} id='All'>All</a></li>
<li><a onClick={(e) => handleCategory(e)} id='Action'>Action</a></li>
<li><a onClick={(e) => handleCategory(e)} id='Adventure'>Adventure</a></li>
<li><a onClick={(e) => handleCategory(e)} id='Survival'>Survival</a></li>
<li><a onClick={(e) => handleCategory(e)} id='Simulation'>Simulation</a></li>
<li><a onClick={(e) => handleCategory(e)} id='Racing'>Racing</a></li>
</ul>
<ul className='main-input'>
<li>
<i className="fas fa-search"></i>
<input type="text" onChange={(e) => handleSearch(e)} placeholder="Search Games..." />
</li>
</ul>
</div>
</section>
<section className="games">
{
filteredPreviews.map(preview => (
<div>
<h3>{preview.title}</h3>
<p>{preview.category}</p>
</div>
))}
</section>
</div>
)
}
export default Home
Sample Data
const previews = [
{
title: "Red Dead Redemption 2",
category: "Survival",
},
{
title: "FEAR",
category: "Horror",
},
{
title: "Battlefield 1",
category: "Action",
},
];
So I have a function that handles the current category that the user clicks on and displays the previews accordingly, but I cannot figure out how I let the user use the search input too, I tried using || conditionals and other things but in the end I couldnt figure it out, any help is appreciated!
import React from "react";
import { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
const previews = [
{
title: "Red Dead Redemption 2",
category: "Survival"
},
{
title: "FEAR",
category: "Horror"
},
{
title: "Battlefield 1",
category: "Action"
}
];
const Home = () => {
const [search, setSearch] = useState({
category: "All",
searchBar: ""
});
const handleCategory = (e) => {
setSearch({ ...search, category: e.target.id });
};
const handleSearch = (e) => {
setSearch({ ...search, searchBar: e.target.value,category :'' });
};
// This only works for the categories
// Now this works for search too
const filteredPreviews = () => {
const { category, searchBar } = search;
if (category === "All" || (searchBar && searchBar === "All")) {
return previews;
}
const filtered = previews.filter((preview) => {
if (
preview.category === category ||
(searchBar && searchBar === preview.category)
) {
return preview;
}
});
return filtered;
};
return (
<div className="container">
<section className="main-nav">
<div className="main-nav-content">
<ul className="categories">
<li>
<a onClick={(e) => handleCategory(e)} id="All">
All
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Action">
Action
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Adventure">
Adventure
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Survival">
Survival
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Simulation">
Simulation
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Racing">
Racing
</a>
</li>
</ul>
<ul className="main-input">
<li>
<i className="fas fa-search"></i>
<input
type="text"
onChange={(e) => handleSearch(e)}
placeholder="Search Games..."
/>
</li>
</ul>
</div>
</section>
<section className="games">
{filteredPreviews().map((preview) => (
<div>
<h3>{preview.title}</h3>
<p>{preview.category}</p>
</div>
))
}
</section>
</div>
);
};
export default Home;
import axios from "axios";
import React from "react";
import { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
const previews = [
{
title: "Red Dead Redemption 2",
category: "Survival"
},
{
title: "FEAR",
category: "Horror"
},
{
title: "Battlefield 1",
category: "Action"
}
];
const Home = () => {
const [search, setSearch] = useState({
category: "All",
searchBar: ""
});
const handleCategory = (e) => {
setSearch({ ...search, category: e.target.id });
};
const handleSearch = (e) => {
setSearch({ ...search, searchBar: e.target.value });
};
// This only works for the categories
// Now this works for search too
const filteredPreviews = () => {
const { category, searchBar } = search;
if (category === "All" || (searchBar && searchBar === "All")) {
return previews;
}
const filtered = previews.filter((preview) => {
if (
preview.category === category ||
(searchBar && searchBar === preview.category)
) {
return preview;
}
});
return filtered;
};
return (
<div className="container">
<section className="main-nav">
<div className="main-nav-content">
<ul className="categories">
<li>
<a onClick={(e) => handleCategory(e)} id="All">
All
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Action">
Action
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Adventure">
Adventure
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Survival">
Survival
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Simulation">
Simulation
</a>
</li>
<li>
<a onClick={(e) => handleCategory(e)} id="Racing">
Racing
</a>
</li>
</ul>
<ul className="main-input">
<li>
<i className="fas fa-search"></i>
<input
type="text"
onChange={(e) => handleSearch(e)}
placeholder="Search Games..."
/>
</li>
</ul>
</div>
</section>
<section className="games">
{filteredPreviews().map((preview) => (
<div>
<h3>{preview.title}</h3>
<p>{preview.category}</p>
</div>
))}
</section>
</div>
);
};
export default Home;

React JS doesn't render on first time

import React, { useState, useRef, useEffect } from "react";
import fire from "../../../config";
import { useAuth } from "../../AuthContext";
import { Grid, Paper, Typography } from "#material-ui/core";
import "./style.css";
import { Link } from "react-router-dom";
import UserReviewComponent from "./UserReviewComponent";
import ReviewComponent from "../Reviews/ReviewComponent";
import ReactPaginate from "react-paginate";
export default function UserReviews() {
const [reviews, setReviews] = useState([]);
const [photo, setPhoto] = useState();
const [state, setstate] = useState();
const { currentUser } = useAuth();
const refItem = fire.firestore().collection("User");
const [loading, setLoading] = useState([true]);
const [vendorDetails, setVendorDetails] = useState([]);
const [error, setError] = useState(0);
const [value, setValue] = useState(0);
const [rating, setRating] = useState(0);
useEffect(() => {
fetchUserDetails();
fetchUserReviews();
}, []);
const [users, setUsers] = useState([]);
const [pageNumber, setPageNumber] = useState(0);
const usersPerPage = 2;
const pagesVisited = pageNumber * usersPerPage;
const pageCount = Math.ceil(users.length / usersPerPage);
const changePage = ({ selected }) => {
setPageNumber(selected);
};
const displayUsers = users
.slice(pagesVisited, pagesVisited + usersPerPage)
.map((v) => {
return (
<ReviewComponent
vendorid={v.vendorId}
rating={v.rating}
review={v.review}
useremail={v.useremail}
username={v.username}
userid={v.userid}
date={v.date}
id={v.id}
/>
);
});
const fetchUserReviews = () => {
fire
.firestore()
.collection("VendorReviews")
.where("useremail", "==", currentUser.email)
.get()
.then((querySnapshot) => {
const item = [];
querySnapshot.forEach((doc) => {
item.push(doc.data());
});
setReviews(item);
setUsers(reviews.slice(0, 50));
});
};
const fetchUserDetails = () => {
refItem.doc(currentUser.email).onSnapshot((doc) => {
if (doc.exists) {
setstate(doc.data().status);
setPhoto(doc.data().photourl);
} else {
console.log("No such document!");
}
});
};
// const getTotalUserRating = () => {
// let totalRating = 0;
// reviews.map((v) => {
// totalRating += v.rating;
// });
// setRating(totalRating);
// setLoading(false);
// };
// if (loading) {
// return <div className="App">Loading...</div>;
// }
return (
<>
<div className="container-1">
<div className="row">
<div className="col-md-12">
<div id="content" className="content content-full-width">
<div className="profile-1">
<div className="profile-header">
<div className="profile-header-cover"></div>
<div className="profile-header-content">
<div className="profile-header-img">
<img src={photo} alt="" />
</div>
<div className="profile-header-info">
<h4 className="m-t-10 m-b-5">
{currentUser.displayName}
</h4>
<p className="m-b-10">{state}</p>
<Link
to={`/user/${currentUser.uid}`}
className="btn btn-sm btn-info mb-2"
>
Edit Profile
</Link>
</div>
</div>
<ul className="profile-header-tab nav nav-tabs">
<li className="nav-item">
<a
href="#profile-post"
className="nav-link active show"
data-toggle="tab"
>
My Reviews
</a>
</li>
</ul>
</div>
</div>
<div className="container">
<div className="col-md-12">
<div className="offer-dedicated-body-left">
<div className="tab-content" id="pills-tabContent">
<div
className="tab-pane fade active show"
id="pills-reviews"
role="tabpanel"
aria-labelledby="pills-reviews-tab"
>
<div className="bg-white rounded shadow-sm p-4 mb-4 restaurant-detailed-ratings-and-reviews">
<h5 className="mb-1">All Ratings and Reviews</h5>
{displayUsers}
<hr />
<hr />
<a
className="text-center w-100 d-block mt-4 font-weight-bold"
href="#"
>
<ReactPaginate
previousLabel={"Previous"}
nextLabel={"Next"}
pageCount={pageCount}
onPageChange={changePage}
containerClassName={"paginationBttns"}
previousLinkClassName={"previousBttn"}
nextLinkClassName={"nextBttn"}
disabledClassName={"paginationDisabled"}
activeClassName={"paginationActive"}
/>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
}
If I edit something on the IDE and then save and then the content appears but there is nothing on the first render. Please help me out. I think its due to pagination and the array has undefined values on the first render and so it returns nothing. The pagination slices the array so that the pagination is implemented.
add following in useEffects dependency array
useEffect(() => {
fetchUserDetails();
fetchUserReviews();
}, [reviews, state, photo, users ]);

How do I close my Modal using the react-modal component?

hi friends i'm having a problem if someone can help me i'll be very grateful, i can't find out why my modal doesn't close using shouldCloseOnOverlayClick = {true} and even without using it it doesn't close either I'll put the code:
components/_App/ModalLogin.js
import React from 'react';
import ReactDOM from 'react-dom';
import Modal from 'react-modal';
import catchErrors from '../../utils/catchErrors';
const INITIAL_USER = {
email: '',
password: ''
}
const ModalLogin = ({isOpen, close }) => {
const [user, setUser] = React.useState(INITIAL_USER);
const [disabled, setDisabled] = React.useState(true);
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState('');
React.useEffect((modal) => {
const isUser = Object.values(user).every(el => Boolean(el));
isUser ? setDisabled(false) : setDisabled(true)
}, [user]);
const handleChange = (e) => {
const { name, value } = e.target;
setUser(prevState => ({ ...prevState, [name]: value }));
}
const handleSubmit = async e => {
e.preventDefault();
try {
setLoading(true);
setError('');
const url = `${baseUrl}/api/login`;
const payload = { ...user };
const response = await axios.post(url, payload);
handleLogin(response.data);
} catch (error) {
catchErrors(error, setError);
} finally {
setLoading(false);
}
}
const customStyles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)'
}
};
console.log(close)
return (
<Modal
isOpen={isOpen}
style={customStyles}
onRequestClose={close}
shouldCloseOnOverlayClick={true}
>
<div className="">
<div className="theme_login_box radius">
<header>
<h1>Fazer Login:</h1>
<p>Informe seu nome e e-mail para fazer login e acessar seus pedidos.</p>
</header>
<form method="POST" onSubmit={handleSubmit}>
<input className="radius" type="email" name="email" value={user.email} onChange={handleChange} placeholder="E-mail:" />
<input className="radius" type="password" name="password" value={user.password} onChange={handleChange} placeholder="Senha:" />
<button className="btn transition radius icon-success" type="submit" href="/" title="Minha conta" >Fazer Login</button>
</form>
Esqueci minha senha
</div>
</div>
</Modal>
)
};
export default ModalLogin;
my file where I invoke the modal:
components/_App/StaticHeader.js
import React from 'react';
import Link from "next/link";
import Router, { useRouter } from 'next/router';
import NProgress from 'nprogress';
import { handleLogout } from '../../utils/auth';
import ModalLogin from './ModalLogin';
import ReactDOM from 'react-dom';
import Modal from 'react-modal';
Router.onRouteChangeStart = () => NProgress.start();
Router.onRouteChangeComplete = () => NProgress.done();
Router.onRouteChangeError = () => NProgress.done();
const StaticHeader = ({ user }) => {
const router = useRouter();
const [menuActive, setMenuActive] = React.useState(false);
const [search, setSearch] = React.useState({ search: '' });
//console.log(user)
const isRoot = user && user.role == 'root';
const isAdmin = user && user.role == 'admin';
const isRootOrAdmin = isRoot || isAdmin;
const [modalIsOpen, setIsOpen] = React.useState(false);
function openModal() {
setIsOpen(true);
}
function closeModal() {
setIsOpen(false);
}
const isActive = (route) => {
return route == router.pathname;
}
const handleOnChange = (e) => {
const { name, value } = e.target;
setSearch(prevState => ({ ...prevState, [name]: value }))
}
const handleSearch = (e) => {
Router.push({
pathname: '/products',
query: { term: search.search }
})
}
const menuToggle = () => {
setMenuActive(!menuActive)
}
return (
<header className="main_header">
<div className="container">
<div className="main_header_nav">
<div className="main_header_nav_logo">
<a href="" title="WdpShoes | Home">
<img alt="logo" title="logo menu" src="/css/themes/logo/wdpshoes_logo_white.png" />
</a>
</div>
<div className="main_header_nav_search">
<form action="" method="post" className="radius">
<input type="text" name="s" placeholder="Pesquisar na loja:" />
<button className="icon-search icon-notext transition"></button>
</form>
</div>
<div className="main_header_nav_menu">
<a className="icon-cart icon-notext transition main_header_nav_menu_cart" href="/cart"><span>3</span></a>
<div className="main_header_nav_menu_user">
<a href="#" title="#" className="icon-user main_header_nav_menu_user_a radius transition" onClick={openModal} >
{modalIsOpen && <ModalLogin isOpen={openModal} close={closeModal}/> }
Login</a>
<nav className="radius">
Meus Pedidos
Meus Pedeidos
Meus endereços
Sair
</nav>
</div>
</div>
</div>
<ul className="main_header_departments">
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_deprtaments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
<li className="main_header_departments_li">
Departamento
<ul className="main_header_departments_li_ul">
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
<li className="main_header_departments_li_ul_li">Categoria</li>
</ul>
</li>
</ul>
</div>
</header>
);
}
export default StaticHeader;
What could I be changing to make my modal work as expected if someone can help me thanks
The issue is that you have encapsulated your modal inside the <a /> tag and in there you have an onClick which calls openModal. Once you click on "close" inside your modal the event propagates and triggers the click on <a /> tag.
To fix the issue just pull put the <Modal /> outside of your <a /> tag.
<a href="#" title="#" className="icon-user main_header_nav_menu_user_a radius transition" onClick={openModal} >Login</a>
{modalIsOpen && <ModalLogin isOpen={modalIsOpen} close={closeModal}/> }
In this line:
{modalIsOpen && <ModalLogin isOpen={openModal} close={closeModal}/> }
The isOpen property should receive a boolean value but instead is receiving a function (openModal). The correct value is isOpen={modalIsOpen}

Resources