REACT: Can´t pass parameter to a lifting up event handler - reactjs

I can´t pass the parameters from a child component to a parent component using the same event handler.
My components' tree follows this structure:
ProductList
ProductsGrid
PaginationBar
In the ProducList component I have this event handler
handlePagination = (index) => { bla bla bla }
<PaginationBar
OnPagination={(index) => this.handlePagination(index)}
pages={this.state.pages}
/>
In the Pagination Bar when I render the page.
render() {
return (
<nav aria-label="Catalog page navigation">
<ul className="pagination">
<li className={this.navButtonEnabled(0)} key="page-item-0">
<a
className="page-link"
onClick={this.props.OnPagination(0)}
href="#"
aria-label="Previous"
>
<span aria-hidden="true">Previous 3</span>
</a>
</li>
<li className={this.navButtonEnabled(1)} key="page-item-1">
<a
className="page-link"
onClick={this.props.OnPagination(1)}
href="#"
>
<span aria-hidden="true">
{this.navButtonDisplay(this.props.pages.navigation[1])}
</span>
</a>
</li>
<li className={this.navButtonEnabled(2)} key="page-item-2">
<a
className="page-link"
onClick={this.props.OnPagination(2)}
href="#"
>
<span aria-hidden="true">
{this.navButtonDisplay(this.props.pages.navigation[2])}
</span>
</a>
</li>
<li className={this.navButtonEnabled(3)} key="page-item-3">
<a
className="page-link"
onClick={this.props.OnPagination(3)}
href="#"
>
<span aria-hidden="true">
{this.navButtonDisplay(this.props.pages.navigation[3])}
</span>
</a>
</li>
<li className={this.navButtonEnabled(4)} key="page-item-4">
<a
className="page-link"
onClick={this.props.OnPagination(4)}
href="#"
aria-label="Next"
>
<span aria-hidden="true">Next 3</span>
</a>
</li>
</ul>
</nav>
);
}
}
In the onClick event, I call the event handler with the index number (this is the parameter I want to pass), according the button clicked I render correctly the ProductsGrid. But it doesn't work at all, I tried several approaches, I just want to pass a number via a parameter for a lifting up event handler. What am I doing wrong?
This is the error presented in the console.
react_devtools_backend.js:6 Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.
in Pagination (created by Catalog)
in Catalog (created by App)
in main (created by App)
in App
I am not changing any state during the render process, the event handler changes the status, when the button is clicked. This is not a render process.

Please replace
onClick={this.props.OnPagination(0)}
With
onClick={() => {this.props.OnPagination(0)}}
Here is complete code (I have commented some code so that I can run this easily to my end):
import React from "react";
export default class ProductList extends React.Component {
handlePagination = (index) => {
console.log(index, 'index');
};
render() {
return (
<PaginationBar OnPagination={(index) => this.handlePagination(index)}
// pages={this.state.pages}
/>
);
}
}
class PaginationBar extends React.Component {
render() {
return (
<nav aria-label="Catalog page navigation">
<ul className="pagination">
<li key="page-item-0">
<a
className="page-link"
onClick={() => {this.props.OnPagination(0)}}
href="#"
aria-label="Previous"
>
<span aria-hidden="true">Previous 3</span>
</a>
</li>
<li key="page-item-1">
<a
className="page-link"
onClick={() => {this.props.OnPagination(1)}}
href="#"
>
<span aria-hidden="true">
{/*{this.navButtonDisplay(this.props.pages.navigation[1])}*/}
Previous 2
</span>
</a>
</li>
<li key="page-item-2">
<a
className="page-link"
onClick={() => {this.props.OnPagination(2)}}
href="#"
>
<span aria-hidden="true">
{/*{this.navButtonDisplay(this.props.pages.navigation[2])}*/}
Previous 1
</span>
</a>
</li>
<li key="page-item-3">
<a
className="page-link"
onClick={() => {this.props.OnPagination(3)}}
href="#"
>
<span aria-hidden="true">
{/*{this.navButtonDisplay(this.props.pages.navigation[3])}*/}
Next 2
</span>
</a>
</li>
<li key="page-item-4">
<a
className="page-link"
onClick={() => {this.props.OnPagination(4)}}
href="#"
aria-label="Next"
>
<span aria-hidden="true">Next 3</span>
</a>
</li>
</ul>
</nav>
);
}
}

Related

How to change background-color of navigation when redirecting from homepage to other pages using useLocation on Scroll in React.js?

BELOW IS MY CODE : HEADER.JS
When I click on shop button in navigation on homepage -> http://localhost:3000/ then it should go to -> http://localhost:3000/product-listing and should add a bg-black class on nav tag and should stay black background.
IMPORTS---
import React, { useState, useEffect } from "react";
import Loading from "../other/Loading";
import PageNotFound from "../other/PageNotFound";
import { NavLink, useLocation } from "react-router-dom";
const Header = () => {
const [loading, setLoading] = useState(true);
const [headerData, setHeaderData] = useState(null);
const [bgBlack, setBgBlack] = useState("");
const [border, setBorder] = useState("");
const [textColor, setTextColor] = useState("");
const location = useLocation();
console.log(location.pathname);
USE EFFECT---
useEffect(() => {
getHeaderData();
window.addEventListener("scroll", changeBackground);
return () => {
window.removeEventListener("scroll", changeBackground);
};
}, []);
GET HEADER NAVIGATION DATA---
const getHeaderData = async () => {
try {
const response = await fetch("http://localhost:8000/navLinks");
const data = await response.json();
if (data) {
setLoading(false);
setHeaderData(data);
} else {
setHeaderData("DATA NOT FOUND");
}
} catch (err) {
if (err) {
console.log("OOPS... SOMETHING WENT WRONG");
}
}
};
CHANGE NAV BACKGROUND-COLOR---
const changeBackground = () => {
if (window.scrollY > 5) {
setBgBlack("bg-black");
setBorder("border-bottom");
setTextColor("text-white");
} else {
setBgBlack("");
setBorder("");
setTextColor("");
}
};
IF LOADING IS TRUE LOAD LOADING COMPONENT---
if (loading) {
return (
<>
<Loading loadingHeader="Loading Header" />
</>
);
}
// console.log(headerData);
RETURN JSX---
return (
<>
{headerData ? (
<header>
<nav
className={`navbar navbar-expand-lg navbar-light ${bgBlack} fixed-top`}
>
<div className="container">
<div>
<button
className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span className="text-white">
<i className="fa fa-bars"></i>
</span>
</button>
</div>
<div className="order-lg-0">
<NavLink className="navbar-brand" to="/">
<img
width="50"
src={headerData.logo.url}
className="img-fluid"
alt=""
/>
</NavLink>
</div>
<div className="order-lg-2 d-lg-none">
<span
className="text-white d-flex"
data-toggle="modal"
data-target="#mobileCartModal"
>
<span className="d-inline-block mr-1">
<i className="fa fa-shopping-cart"></i>
</span>
<span className="d-inline-block">0</span>
</span>
</div>
<div
className="collapse navbar-collapse order-lg-1"
id="navbarSupportedContent"
>
<ul className="navbar-nav mr-auto px-3">
{/* <li className="nav-item dropdown">
<a
className="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Packages
</a>
<div
className="dropdown-menu"
aria-labelledby="navbarDropdown"
>
<a className="dropdown-item" href="product.html">
Subscriptions
</a>
<a className="dropdown-item" href="product.html">
Value Packs
</a>
</div>
</li>
<li className="nav-item dropdown">
<a
className="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Juices
</a>
<div
className="dropdown-menu"
aria-labelledby="navbarDropdown"
>
<a className="dropdown-item" href="product.html">
Juices
</a>
<a className="dropdown-item" href="product.html">
Almond Milks
</a>
<a className="dropdown-item" href="product.html">
Protien Milkshake
</a>
<a className="dropdown-item" href="product.html">
Cleanses
</a>
</div>
</li> */}
<li className="nav-item">
<NavLink
className="nav-link"
to="/product-listing"
data-toggle="modal"
data-target="#loginModal"
>
Shop
</NavLink>
</li>
<li className="nav-item dropdown">
<a
className="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
>
Learn
</a>
<div
className="dropdown-menu"
aria-labelledby="navbarDropdown"
>
<a className="dropdown-item" href="#">
Process
</a>
<a className="dropdown-item" href="#">
About Us
</a>
<a className="dropdown-item" href="#">
Blog
</a>
<a className="dropdown-item" href="#">
News
</a>
<a className="dropdown-item" href="#">
Beyond The Bottle
</a>
</div>
</li>
<li className="nav-item">
<a
className="nav-link"
href="#"
data-toggle="modal"
data-target="#loginModal"
>
Login
</a>
</li>
<li className="nav-item">
<a
className="nav-link"
href="#"
data-toggle="modal"
data-target="#signupModal"
>
Sign Up
</a>
</li>
</ul>
<form className="dvSearch my-2 my-lg-0 px-3 position-relative">
<input
className={`form-control mr-sm-2 ${border}`}
type="text"
placeholder="Search"
aria-label="Search"
/>
<button
className="btn my-2 my-sm-0 position-absolute"
type="submit"
>
<i className={`fa fa-search ${textColor}`}></i>
</button>
</form>
</div>
</div>
</nav>
</header>
) : (
<PageNotFound />
)}
</>
);
};
EXPORT DEFAULT HEADER.JS---
export default Header;

How to capture bootstrap dropdown values in react without third-party libraries?

I am using bootstrap 5.1 without third-party libaries like react-bootstrap or ... in my React App.
I am able to see the dropdown button is working properly on my react app but I cannot capture the values on selecting different options of drop down. I tried to replace the <a> tags with <option value='...'> but wasn't successful . Any idea ?
<div class="dropdown">
<a class="btn btn-secondary dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-bs-toggle="dropdown" aria-expanded="false">
Dropdown link
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</div>
The a tag doesn't support value attribute (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a).
Similarly, you can't have option tag without a select/datalist/optgroup (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option).
If you need some type of value associated with the tags anyway, use something like: data-value={your_value}. And then work with the dataset of the element clicked.
You can try with the below code
export default function App() {
const onChangeClick = (value) => {
console.log(value);
};
return (
<div class="dropdown">
<a
class="btn btn-secondary dropdown-toggle"
href="#"
role="button"
id="dropdownMenuLink"
data-bs-toggle="dropdown"
aria-expanded="false"
>
Dropdown link
</a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenuLink">
<li>
<a
class="dropdown-item"
href="#"
onClick={() => onChangeClick("action")}
>
Action
</a>
</li>
<li>
<a
class="dropdown-item"
href="#"
onClick={() => onChangeClick("another action")}
>
Another action
</a>
</li>
<li>
<a
class="dropdown-item"
href="#"
onClick={() => onChangeClick("else action")}
>
Something else here
</a>
</li>
</ul>
</div>
);
}

I have to click on my link twice before state is update and styling is changed

i have an issue. I want the styling of my Link to change based on a state. But the issue is that, i have to click on the link twice before the styling is updated. But when i use the e.prevetndefault, the styling is applied when i click the link but I cannot go to the page. Here is the code.
function Footer(){
const [activeValue, setIsActive] = useState("0")
return(
<div className="footer">
<ul className="socials">
<li> <i className="fab fa-facebook-f"></i> </li>
<li> <i className="fab fa-instagram"></i> </li>
<li> <i className="fab fa-twitter"></i> </li>
<li> <i className="fas fa-podcast"></i> </li>
<li></li>
<li><Link to="/peepNews" onClick={()=>{setIsActive("1")}} style={activeValue=="1"?{color:"#0B77BE",fontWeight:"600"}:null} >Peep News</Link></li>
<li><Link to="/faq" onClick={()=>{setIsActive("2")}} style={activeValue=="2"?{color:"#0B77BE",fontWeight:"600"}:null} >FAQ</Link></li>
<li><a href="" style={{color:"gray", fontWeight:"200"}}>Careers</a></li>
<li><Link to="/legal" onClick={()=>{setIsActive("3")}} style={activeValue=="3"?{color:"#0B77BE",fontWeight:"600"}:null} >Legal</Link></li>
<li>Jupe Global </li>
</ul>
</div>
);
}
EDIT:
This is when i added the useEffect hook. But the issue is that whenever the page re-render, the activeValue is set back to the default Value(0) instead of 1,2,3 etc.
function Footer(){
const [activeValue, setIsActive] = useState("0")
useEffect(() => {
setIsActive(activeValue) ;
alert(activeValue);
},[activeValue])
return(
<div className="footer">
<ul className="socials">
<li> <i className="fab fa-facebook-f"></i> </li>
<li> <i className="fab fa-instagram"></i> </li>
<li> <i className="fab fa-twitter"></i> </li>
<li> <i className="fas fa-podcast"></i> </li>
<li></li>
<li><Link to="/peepNews" onClick={()=>{setIsActive("1")}} style={activeValue=="1"?{color:"#0B77BE",fontWeight:"600"}:null} >Peep News</Link></li>
<li><Link to="/faq" onClick={()=>{setIsActive("2")}} style={activeValue=="2"?{color:"#0B77BE",fontWeight:"600"}:null} >FAQ</Link></li>
<li><a href="" style={{color:"gray", fontWeight:"200"}}>Careers</a></li>
<li><Link to="/legal" onClick={()=>{setIsActive("3")}} style={activeValue=="3"?{color:"#0B77BE",fontWeight:"600"}:null} >Legal</Link></li>
<li>Jupe Global </li>
</ul>
</div>
);
}
With react-router you don't need to use the Link element to navigate to a new page, particularly if you want to functionality to be a little more complex.
You can create a history file and export a history object:
import { createBrowserHistory } from 'history';
export default createBrowserHistory();
Then import history into any file where you would like to navigate using javascript. Then in your file you can simply create a which you can style as you please (or continue to use with e.preventDefault()) which then navigates on the click action.
<li>
<div
onClick={() => {
setIsActive("1");
history.push("/peepNews");
}}
style={activeValue == "1" ? { color: "#0B77BE", fontWeight: "600" } : undefined} >
Peep News</div>
</li>

Pass items of menu and use map also I want to use default props in reactjs

I'm new to react.js. in my code, I would like to pass these menu items such as dashboard, Customer,.. as props, and I would like to use a map on it. but t i got the same icon <i className="fas fa-home mr-3"> for all of the menu items. also how I can use the default props for them? could you explain this in two ways ( map and default props)
import "./Sidebar.css";
import React, { Component } from "react";
class Sidebar extends Component {
constructor(props) {
super(props);
this.state = {
menuItems: [
"Dashboard",
"Customer",
"Category",
"Transaction",
"Pick-up",
"Stock",
"Financial",
"Report",
],
};
}
render() {
return (
<div className="wrapper d-flex align-items-stretch">
<nav id="sidebar">
<div className="custom-menu">
<button
type="button"
id="sidebarCollapse"
className="btn btn-primary"
>
<i className="fa fa-bars"></i>
<span className="sr-only">Toggle Menu</span>
</button>
</div>
<div className="p-4">
<h1>
<a href="index.html" className="logo">
Donyaro{" "}
</a>
</h1>
<ul className="list-unstyled components mb-5">
{this.state.menuItems&&this.state.menuItems.lenght?this.state.menuItems:[]}
{this.state.menuItems.map((item) => (
<li className="active">
<a href={" "}>
<i className="fas fa-home mr-3"></i>
{item}
</a>
</li>
))}
</ul>
</div>
<div class="footer">
<a href={" "}>
<i className="fas fa-caret-down"></i>
</a>
<h6>
<span>Welcome, </span>
<a href="index.html" className="add-business">
Add Business
</a>
</h6>
</div>
</nav>
</div>
);
}
}
export default Sidebar;
map is a pure function that returns new array based on an array exmple :
const array=[1,2,3,4];
const newArr=array.map(el=>el+'a')
console.log(newArr)=>["1a", "2a", "3a", "4a"];
this is all map doing it iterate over every element of the old array and gives
back a new array based on what you want to do with the old array.it is very
useful.
I think you do the function right but your problem is with jsx you should wrap your
li element with a div like this
{this.state.menuItems.map((item) => (
<div>
<li className="active">
<a href={" "}>
<i className="fas fa-home mr-3"></i>
{item}
</a>
</li>
</div>
))}
**

Get the drop down items in the console in React js

I need to fetch the clicked dropdown item and log it in the console using React js.
Code:
<div onClick={this.handleSearchBtn} className="dropdown-menu">
<a className="search-item dropdown-item" href="#" >Authors</a>
<a className="search-item dropdown-item" href="#">Article Title</a>
<a className="search-item dropdown-item" href="#">PMID</a>
<a className="search-item dropdown-item" href="#">Mesh Terms</a>
</div>
From my understanding, you can do something like this
class Anchor extends React.Component {
state = {
selected: ''
}
handleSearchBtn = (event) => {
if (event.target.className.indexOf("search-item") !== -1) {
this.setState({ selected: event.target.text });
}
};
render() {
return (
<div onClick={this.handleSearchBtn} className="dropdown-menu">
selected: {this.state.selected}
<a className="search-item dropdown-item" href="#">
Authors
</a>
<a className="search-item dropdown-item" href="#">
Article Title
</a>
<a className="search-item dropdown-item" href="#">
PMID
</a>
<a className="search-item dropdown-item" href="#">
Mesh Terms
</a>
</div>
);
}
}
ReactDOM.render(<Anchor />, document.getElementById("root"));
Here is the demo
Hope it helps :)

Resources