Im working on a custom toast notification. But the hard part to me is I've not been able to hide the toast notification correctly. When I make a click to show it the toast has an animation to the left the problem is when the toast is gonna hide just disapear and it does not slide to the right. Im working with react and tailwind css. Here is the code. also leave a link to the case. https://codesandbox.io/s/toast-notification-ucx2v?file=/src/components/toastNotification.jsx
I hope you can help me guys.
-----App component-----
import { useEffect, useState } from "react";
import ToastNotification from "./components/toastNotification";
import "./styles.css";
export default function App() {
const [showToast, setShowToast] = useState(false);
const addToCart = () => {
setShowToast(true);
};
useEffect(() => {
setTimeout(() => {
setShowToast(false);
}, 3000);
}, [showToast]);
return (
<div className="App">
<ToastNotification showNotification={showToast} />
<button
className="w-1/2 p-2 flex items-center justify-center rounded-md bg-indigo-400 text-white"
type="submit"
onClick={addToCart}
>
Add to cart
</button>
</div>
);
}
-----Toast component-----
import React, { useEffect, useState } from "react";
const ToastNotification = ({ showNotification }) => {
useEffect(() => {
setTimeout(() => {}, 5000);
}, []);
return (
<>
{showNotification === false ? null : (
<div className="static z-20">
<div
className={`${
showNotification
? "animate__animated animate__slideInRight absolute top-16 right-4 flex items-center text-white max-w-sm w-full bg-green-400 shadow-md rounded-lg overflow-hidden mx-auto"
: "animate__animated animate__slideOutRight absolute top-16 right-4 flex items-center text-white max-w-sm w-full bg-green-400 shadow-md rounded-lg mx-auto"
}`}
>
<div class="w-10 border-r px-2">
<i class="far fa-check-circle"></i>
</div>
<div class="flex items-center px-2 py-3">
<div class="mx-3">
<p>add to car</p>
</div>
</div>
</div>
</div>
)}
</>
);
};
export default ToastNotification;
Related
In console this error is getting displayed:
enter image description here
Everything is fine but navbar is not getting displayed with the error above.
Here is my App.js file
import Navbar from './components/Navbar';
import './App.css';
import AddEmployee from './components/AddEmployee';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import EmployeeList from './components/EmployeeList';
function App() {
return (
<>
<BrowserRouter>
<Navbar/>
<Routes>
<Route index element={<EmployeeList/>}/>
<Route path="/" element={<EmployeeList/>}></Route>
<Route path ="/employeeList" element={<EmployeeList/>}></Route>
<Route path ="/addEmployee" element={<AddEmployee/>}></Route>
</Routes>
</BrowserRouter>
</>
);
}
export default App;
Navbar.js
import React from 'react'
const Navbar = () => {
return (
<div className="bg-gray-800">
<div className='h-16 px-8 flex items-center'>
<p className='text-white font-bold'>Employee Management System </p>
</div>
</div>
)
}
export default Navbar;
AddEmployee.js
import React, {useState} from 'react'
import employeeService from '../services/employeeService';
const AddEmployee = () => {
const [employee, setEmployee] = useState({
id: "",
firstName: "",
lastName: "",
emailId: "",
})
const handleChange = (e) => {
const value = e.target.value;
setEmployee({...employee,[e.target.name] : value});
}
const saveEmployee = e => {
e.preventDefault();
employeeService.saveEmployee(employee).then((response) =>{
console.log(response);
}).catch((err) => {
console.log(err);
})
}
return (
<div className="flex max-w-2xl mx-auto shadow border-b">
<div className="px-8 py-8">
<div className="font-thin text-2xl tracking-wider">
<h1>Add New Employee</h1>
</div>
<div className="justify-center items-center h-14 w-full my-4">
<label className="block text-gray-600 text-sm font-normal" >First Name</label>
<input className="h-10 w-96 border mt-2 px-2 py-2"
type="text"
value = {employee.firstName}
onChange = {(e) => handleChange(e)}
name="firstName"></input>
</div>
<div className="justify-center items-center h-14 w-full my-4">
<label className="block text-gray-600 text-sm font-normal" >Last Name</label>
<input className="h-10 w-96 border mt-2 px-2 py-2"
type="text"
value = {employee.lastName}
onChange = {(e) => handleChange(e)}
name="lastName"></input>
</div>
<div className="justify-center items-center h-14 w-full my-4">
<label className="block text-gray-600 text-sm font-normal" >E-Mail</label>
<input className="h-10 w-96 border mt-2 px-2 py-2"
type="email"
value = {employee.emailId}
onChange = {(e) => handleChange(e)}
name="emailId"></input>
</div>
<div className="justify-center items-center h-14 w-full my-4 space-x-4">
<button
className="rounded text-white font-semibold bg-red-600 px-6 hover:bg-green-500 py-2"
onClick={saveEmployee}>
Save
</button>
<button
className="rounded text-white font-semibold bg-orange-600 px-6 hover:bg-green-500 py-2"
>
Clear
</button>
</div>
</div>
</div>
)
}
export default AddEmployee;
It doesnot contain much but just check if there is any error
EmployeeList.js
import React from 'react'
const EmployeeList = () => {
return (
<div>EmployeeList</div>
)
}
export default EmployeeList;
when i am using addEmployee route navbar is working properly but this error persists even then.
Be sure that BrowserRouter is the first element in the Return
<BrowserRouter>
<>
<Navbar/>
<Routes>
....
</>
</BrowserRouter>
I want to render this popover panel
<Popover.Panel className="absolute z-10 inset-x-0 transform shadow-xl pb-2 w-max">
<div>
<Dropdown subCategory={mainCatArray}/>
</div>
</Popover.Panel>
same as this popover button render in this below code. Because I want to render a separate popover panel with the popover button, please help me to do that. (I cannot render in one categoryObj because I want to render this popover button horizontally, but if I use a single map for the entire popover component popover button renders it vertically.
(Simply What I want to do is I want to render one <Popover.Panel> to one <Popover.Button>)
import { Fragment, useEffect, useState } from "react";
import { Popover, Transition } from "#headlessui/react";
import Dropdown from "./dropdown";
import { categoryObj } from "../../components/item/categoriesobj";
function classNames(...classes) {
return classes.filter(Boolean).join(" ");
}
const CatDropDown = () => {
const [mainCatArray, setMainCatArray] = useState([]);
return (
<>
<Popover className="z-0 relative">
{({ open }) => (
<>
<div>
<div className=" z-10 bg-white">
<div className="w-2/3 flex gap-5 px-4 py-6 sm:px-6 lg:px-8 ">
{categoryObj.map((singleMainCategory) => (
<Popover.Button
className={classNames(
open ? "text-gray-900" : "text-gray-900",
"group bg-white rounded-md inline-flex items-center text-sm font-susty focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-white"
)}
>
<span
key={singleMainCategory.id}
onClick={() => {
setMainCatArray(singleMainCategory.subCategory);
}}
>
<span>{singleMainCategory.name}</span>
</span>
</Popover.Button>
))}
</div>
</div>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 -translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 -translate-y-1"
>
<Popover.Panel className="absolute z-10 inset-x-0 transform shadow-lg pb-2">
<div>
<Dropdown subCategory={mainCatArray}/>
</div>
</Popover.Panel>
</Transition>
</>
)}
</Popover>
</>
);
};
export default CatDropDown;
I've created my navbar such that, when I open it in a mobile device, body gets overflow-hidden class applied. When the navbar is closed, overflow-hidden is removed from body.
Problem encountered: The function which removes overflow-hidden from body doesn't get run when I click on the link and it navigates to another view. Which means, on the new page, body has overflow hidden so the user can't really scroll anywhere. Opening and closing the navbar fixes that since it removes overflow hidden from the body.
I'm using Laravel Breeze with ReactJS.
// NavLink.js
import React, { useEffect, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { Link } from "#inertiajs/inertia-react";
export default function NavLink({ href, active, children, className = "" }) {
return (
<Link
href={href}
className={
(active
? "inline-flex items-center px-1 pt-1 border-b-2 border-[#ed8686] text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-[#E05D5D] transition duration-150 ease-in-out dark:text-gray-400"
: "inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out dark:text-gray-300 dark:hover:text-gray-500 dark:hover:border-gray-300 dark:focus:outline-none dark:focus:text-gray-500 dark:focus:border-gray-300") +
` ${className}`
}
>
{children}
</Link>
);
}
// NavBar.js
import ApplicationLogo from "#/Components/ApplicationLogo";
import DarkModeButton from "#/Components/DarkModeButton";
import NavLink from "#/Components/NavLink";
import { Link } from "#inertiajs/inertia-react";
import React, { useEffect, useRef, useState } from "react";
import { MdClose, MdMenu } from "react-icons/md";
const NavBar = ({ dark, setDark }) => {
const [scrollTop, setScrollTop] = useState("");
const navRef = useRef();
const mobileNavRef = useRef();
const toggleNav = (e) => {
e.preventDefault();
const navBar = mobileNavRef.current;
navBar.classList.toggle("active");
document.body.classList.toggle("overflow-hidden");
};
const hideNav = (e) => {
e.preventDefault();
const navBar = mobileNavRef.current;
navBar.classList.remove("active");
document.body.classList.remove("overflow-hidden");
};
// TODO: Too many renders, change to remove extra renders
useEffect(() => {
if (scrollTop >= 80) {
navRef.current.classList.add("scrolled");
} else {
navRef.current.classList.remove("scrolled");
}
const onScroll = (e) => {
setScrollTop(e.target.documentElement.scrollTop);
};
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, [scrollTop]);
return (
<>
<nav className="main-nav" ref={navRef}>
<Link to="/" className="h-full w-auto block py-4 mx-auto">
<ApplicationLogo className="h-full w-auto" dark={!!dark} />
</Link>
<MdMenu
className="fixed right-4 top-4 text-lg cursor-pointer lg:hidden dark:text-white"
onClick={(e) => toggleNav(e)}
/>
<ul className="hidden lg:flex flex-row items-center justify-center">
<li>
<NavLink
href={route("home")}
active={route().current("home")}
children="Home"
className="text-lg my-2 mx-4"
/>
</li>
<li>
<NavLink
href={route("gallery")}
children="Gallery"
active={route().current("gallery")}
className="text-lg my-2 mx-4"
/>
</li>
<li>
<NavLink
// href={route("about")}
children="About"
active={route().current("about")}
className="text-lg my-2 mx-4"
/>
</li>
<li className="cursor-pointer flex items-center justify-center">
<DarkModeButton dark={dark} setDark={setDark} />
</li>
</ul>
</nav>
<ul
className="w-full md:w1/2 lg:w-1/4 flex items-center justify-center fixed inset-0 bg-white h-full flex-col mobile-nav lg:hidden z-50 dark:bg-gray-900"
ref={mobileNavRef}
>
<MdClose
className="absolute top-4 right-4 text-lg cursor-pointer lg:hidden dark:text-white"
onClick={(e) => hideNav(e)}
/>
<Link to="/" onClick={(e) => hideNav(e)}>
<ApplicationLogo
className="h-32 mb-2 w-auto lg:hidden"
dark={dark}
/>
</Link>
<li>
<NavLink
href={route("home")}
active={route().current("home")}
children="Home"
className="text-lg my-2 mx-4"
onClick={(e) => hideNav(e)}
/>
</li>
<li>
<NavLink
href={route("gallery")}
children="Gallery"
active={route().current("gallery")}
className="text-lg my-2 mx-4"
onClick={(e) => hideNav(e)}
/>
</li>
<li>
<NavLink
// href={route("about")}
children="About"
active={route().current("about")}
className="text-lg my-2 mx-4"
onClick={(e) => hideNav(e)}
/>
</li>
<li className="cursor-pointer">
<DarkModeButton dark={dark} setDark={setDark} />
</li>
</ul>
</>
);
};
export default NavBar;
I've made the function hideNav() which has e.preventDefault() but I'm guessing it doesn't work because it doesn't apply directly on the Link tag? I'm not sure
Unsure how to tackle this problem
I've thought about using useNavigate but I am not using react router dom, inertiajs is handling the routing for me, I just set the routes in laravel web.php file.
I've come up with a solution,
It's not the ideal solution but this is what I can think of
I added a prop to NavLink component and based on if that prop is true, I add onclick event handler that removes overflow class from body
import React from "react";
import { Link } from "#inertiajs/inertia-react";
import { Inertia } from "#inertiajs/inertia";
export default function NavLink({
href,
active,
children,
className = "",
mobileLink = false,
}) {
return (
<Link
href={href}
className={
(active
? "inline-flex items-center px-1 pt-1 border-b-2 border-[#ed8686] text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-[#E05D5D] transition duration-150 ease-in-out dark:text-gray-400"
: "inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out dark:text-gray-300 dark:hover:text-gray-500 dark:hover:border-gray-300 dark:focus:outline-none dark:focus:text-gray-500 dark:focus:border-gray-300") +
` ${className}`
}
onClick={
mobileLink
? (e) => {
e.preventDefault();
document.body.classList.remove("overflow-hidden");
Inertia.visit(href);
}
: undefined
}
>
{children}
</Link>
);
}
I am implementing a modal in my react app but face the weird error, Error: Expected `onClick` listener to be a function, instead got a value of `object` type.. What's confusing here is the fact that I have implemented the modal in another part of the application using the same logic and it doesn't produce such error.
Below are important snippets of the code.
index.js
import React, { useState } from "react";
import ProfileSave from "../../components/modal/profileSave";
const test = () => {
const [saveModal, setSaveModal] = useState(false);
const [save, setSave] = useState(false);
return (
<>
<button className="w-[165px] h-[60px] text-center px-4 py-2 text-sm text-white bg-[#3A76BF] rounded-md font-bold text-[16px]" onClick={saveShowModal}>
Save
</button>
{saveModal && (
<ProfileSave
open={saveModal}
handleClose={() => setSaveModal(!saveModal)}
handleSave={handleSave}
/>
)}
</>
export default test
profileSave.js
import React from "react";
const ProfileSave = (open, handleClose, handleModal) => {
return open ? (
<div className="fixed inset-0 z-10 overflow-y-auto">
<div
className="fixed inset-0 w-full h-full bg-black opacity-40"
onClick={handleClose}
></div>
</div>
) : (
""
);
};
export default ProfileSave;
You neet to extract the props that you component recive
Try this :
import React from "react";
const ProfileSave = ({open, handleClose, handleModal}) => {
return open ? (
<div className="fixed inset-0 z-10 overflow-y-auto">
<div
className="fixed inset-0 w-full h-full bg-black opacity-40"
onClick={handleClose}
></div>
</div>
) : (
""
);
};
export default ProfileSave;
Hey Guys I'm pretty new to React and I'm running into a bit of a pickle here.
I'm making a simple CRUD website creator and I've got the add and delete function created and they work great! but I'm having trouble with the edit function.
I've based this on the this tutorial which works with String data-type
https://www.digitalocean.com/community/tutorials/react-crud-context-hooks
So in my mind this is how it should should work
I've got use state as passing an object with a couple of properties
const [selectedSection, setSelectedSection] = useState({
id: null,
section: {},
});
I've set the id to the current component I'm editing with
const currentSectionId = route.match.params.id;
in my useEffect I'm carrying over the current id with while setting the new compenent skipping the id in the current section
useEffect(() => {
const sectionId = currentSectionId;
const selectedSection = sections.find(
(currentSectionTraversal) => currentSectionTraversal.id === parseInt(sectionId)
);
setSelectedSection(selectedSection);},[currentSectionId, sections]);
const onSubmit = (e) => {
e.preventDefault();
editSection(selectedSection);
history.push("/");
console.log("selectedSection id",selectedSection.section, selectedSection.id)
};
and the button function to spread the selectedSection and change the only the requested value in the button.
const handleOnChange = (userKey, newValue) => setSelectedSection({ ...selectedSection, [userKey]: newValue });
in my render code I've got my button set up like
<button href="/" className="bg-green-400 w-mt hover:bg-green-500 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
value={selectedSection.section}
onChange={() => handleOnChange("section", QuickLinks)}
type="submit"
>Add Section</button>
Now I've tried different things like changing the data-type in the useState Object, having the setSelectedSection in use effect to change the SelectedSection.section
but in the console what I'm noticing is the button is not carrying the data over.
I've imported my compenent as Quicklinks but I'm not sure why it's not passing the component into the selectedSection.section
here is the entire code of the editSection
import React, { useState, useContext, useEffect} from "react";
import { useHistory, Link } from "react-router-dom";
import { GlobalContext } from "./GlobalState";
import QuickLinks from '../components/sections/quick_links/quickLinks';
import QuickLinksPreview from './images/quick-link.jpg';
export const EditSection = (route) => {
let history = useHistory();
const { sections, editSection } = useContext(GlobalContext);
const [selectedSection, setSelectedSection] = useState({
id: null,
section: {},
});
const currentSectionId = route.match.params.id;
useEffect(() => {
const sectionId = currentSectionId;
const selectedSection = sections.find(
(currentSectionTraversal) => currentSectionTraversal.id === parseInt(sectionId)
);
setSelectedSection(selectedSection);
}, [currentSectionId, sections]);
const onSubmit = (e) => {
e.preventDefault();
editSection(selectedSection);
history.push("/");
console.log("selectedSection id",selectedSection.section, selectedSection.id)
};
const handleOnChange = (userKey, newValue) => setSelectedSection({ ...selectedSection, [userKey]: newValue });
if (!selectedSection || !selectedSection.id) {
return <div>Invalid Employee ID.</div>;
}
return (
<React.Fragment>
<div className="w-full container mt-20 mx-auto">
<form onSubmit={onSubmit}>
<table>
<tbody>
{/* ----------------------------Item List Start COPY------------------------ */}
<tr>
<td className="px-6 py-4 whitespace-nowrap">
<div className="flex items-center">
<div className="flex-shrink-0 h-40 w-50 shadow">
<img className="h-40 w-full " src={QuickLinksPreview} alt="" />
</div>
</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm text-gray-900">Quick Links</div>
<div className="text-sm text-gray-500">Multi Card Quick Links<br></br>for Description and links</div>
</td>
<td className="px-6 py-4 whitespace-nowrap">
<span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-100 text-white-800"> Beta </span>
{/* Component Development Status
<span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-black-800"> Constrution </span>
<span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"> Active </span>
<span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-black-800"> Testing </span>
*/}
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">S03-S5</td>
{/* Pricing Levels as Structure
S = Labels that it is sections
02 = is the Template Id for Developers
S = Standard Price
3 = Price level
*/}
<td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button href="/" className="bg-green-400 w-mt hover:bg-green-500 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
value={selectedSection.section}
onChange={() => handleOnChange("section", QuickLinks)}
type="submit"
>Add Section</button>
</td>
</tr>
{console.log("Selected section", selectedSection.section)}
{/* ----------------------------Item List END COPY------------------------ */}
</tbody>
</table>
<div className="flex items-center justify-between">
<div className="block mt-5 bg-red-400 w-full hover:bg-red-500 text-white font-bold py-2 px-4 rounded focus:text-gray-600 focus:shadow-outline">
<Link to="/">Cancel</Link>
</div>
</div>
</form>
</div>
</React.Fragment>
);
};
Try using onClick instead of onChange for the button. I think onChange is for <input> tags not buttons. Also href is for links, not buttons. Unless this button is in a form type=submit isn't necessary. Also an arrow function isn't required for onClick. onChange={() => handleOnChange("section", QuickLinks)} -> onClick={handleOnChange("section", QuickLinks)}.