I am wanting to hide other sibling divs (dropdowns in my case) when I click the statusPillDropdown
so far I click I am setting the status to true and opening the div,
{DropDown ${toggleStatusDropdown ? "open": ""}}
Do I just need to set the state to false for previously opened ones? Not sure how to do this.
thank you
import React, { useState } from "react";
import "./StatusPillDropdown.scss";
function StatusPillDropdown({
cellData,
rowItemId,
onStatusPillDropdownChange
}) {
const [toggleStatusDropdown, setToggleStatusDropdown] = useState();
const toggleDropdown = (action, rowItemId, e) => {
if (action === "pillClick") {
setToggleStatusDropdown(true);
} else {
onStatusPillDropdownChange(rowItemId, e.target.getAttribute("value"));
setToggleStatusDropdown(false);
}
};
const renderstatusPillDropdown = (cellData, rowItemId) => (
<React.Fragment>
<span
className="statusPillDropdown"
onClick={() => toggleDropdown("pillClick", rowItemId)}
>
<span className={`status-pill ${cellData.type}`}>{cellData.text}</span>
</span>
<div className="status">
<div className="dropdown-container">
<div className={`DropDown ${toggleStatusDropdown ? "open" : ""}`}>
<ul>
<li
value="Information only"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span></span>Information only
</li>
<li
value="Unresolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="unresolved"></span>Unresolved
</li>
<li
value="Partially Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="partyResolved"></span>Partially Resolved
</li>
<li
value="Fully Resolved"
onClick={e => toggleDropdown("liClick", rowItemId, e)}
>
<span className="resolved"></span>Fully Resolved
</li>
</ul>
</div>
</div>
</div>
</React.Fragment>
);
return (
<React.Fragment>
{renderstatusPillDropdown(cellData, rowItemId)}
</React.Fragment>
);
}
export default StatusPillDropdown;
Related
The issue is lying in my Sean Connery and Roger Moore list of movies buttons. When I click on Sean Connery List of Movies, it displays Connery movies on Roger Moore's list too, and vice versa.
Prettier 2.7.1
Playground link
--parser babel
Input:
import React, { useState } from "react";
import styled from "styled-components";
import axios from "axios";
const Button = styled.button`
background-color: black;
color: white;
font-size: 20px;
padding: 10px 60px;
border-radius: 5px;
margin: 10px 0px;
cursor: pointer;
`;
function ButtonClick() {
const [users, setUsers] = useState();
const fetchData = (type) => {
axios
.get(
"https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies"
)
.then((response) => {
console.log(response.data)
const mappedArray = response.data
.map(
(item) =>
item[type] ||
(type === "directors" && item.director) ||
(type === "title_song" && item.title_song) ||
(type === "movie_year" && item.movie_year)
)
.filter((uniqueVal) => uniqueVal);
setUsers({ [type]: Array.from([...new Set(mappedArray)]) });
// console.log(movies)
});
};
const [movies, setMovies] = useState();
const fetchMovieData = (name) => {
axios
.get(
"https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies"
).then(response => {
console.log(response.data)
setMovies(response.data.filter(item => item.bond_actor === name).map(item => item.movie_title));
console.log("Hello World")
console.log("Hello World")
// console.log()
})
};
return (
<div>
<div>
<h2>Bond Database</h2>
<h5>
Click on the buttons to see the list of all the bond movie's
directors, bond actors, release year, and title songs
</h5>
<Button onClick={() => fetchData("bond_actor")}>Bond Actors</Button>
{users && (
<ul>
{users?.bond_actor?.map((user, index) => (
<li key={index}>
<a href="https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies">
{user}
</a>
</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("directors")}>Directors</Button>
{users && (
<ul>
{users?.directors?.map((director) => (
<li key={director}>{director}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("title_song")}>Songs</Button>
{users && (
<ul>
{users?.title_song?.map((title_song) => (
<li key={title_song}>{title_song}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("movie_year")}>Movie Year</Button>
{users && (
<ul>
{users?.movie_year?.map((movie_year) => (
<li key={movie_year}>{movie_year}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchMovieData("Sean Connery")}>Sean Connery's List of Movies</Button>
{movies && (
// console.log(movies),
<ul>
{movies?.map((movie) => (
// console.log(movie),
<li key={movie}>{movie}</li>
))}
</ul>
)
}
</div>
<div>
<Button onClick={() => fetchMovieData("Roger Moore")}>Roger Moore List of Movies</Button>
{movies && (
<ul>
{movies?.map((movie) => (
// console.log(moviesR),
<li key={movie}>{movie}</li>
))}
</ul>
)}
</div>
</div>
);
}
export default ButtonClick;
I'd assume the issue is that both buttons are using the same state, but since the names have spaces, I don't know how to create different states for the two buttons. If I get some assistance on this, it would be much appreciated.
You can follow this:
import React, { useState } from "react";
import styled from "styled-components";
import axios from "axios";
const Button = styled.button`
background-color: black;
color: white;
font-size: 20px;
padding: 10px 60px;
border-radius: 5px;
margin: 10px 0px;
cursor: pointer;
`;
function ButtonClick() {
const [users, setUsers] = useState();
const fetchData = (type) => {
axios
.get(
"https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies"
)
.then((response) => {
console.log(response.data);
const mappedArray = response.data
.map(
(item) =>
item[type] ||
(type === "directors" && item.director) ||
(type === "title_song" && item.title_song) ||
(type === "movie_year" && item.movie_year)
)
.filter((uniqueVal) => uniqueVal);
setUsers({ [type]: Array.from([...new Set(mappedArray)]) });
// console.log(movies)
});
};
const [movies, setMovies] = useState({});
const fetchMovieData = (name) => {
axios
.get(
"https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies"
)
.then((response) => {
console.log(response.data);
setMovies({
[name]: response.data
.filter((item) => item.bond_actor === name)
.map((item) => item.movie_title)
});
console.log("Hello World");
console.log("Hello World");
// console.log()
});
};
return (
<div>
<div>
<h2>Bond Database</h2>
<h5>
Click on the buttons to see the list of all the bond movie's
directors, bond actors, release year, and title songs
</h5>
<Button onClick={() => fetchData("bond_actor")}>Bond Actors</Button>
{users && (
<ul>
{users?.bond_actor?.map((user, index) => (
<li key={index}>
<a href="https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies">
{user}
</a>
</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("directors")}>Directors</Button>
{users && (
<ul>
{users?.directors?.map((director) => (
<li key={director}>{director}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("title_song")}>Songs</Button>
{users && (
<ul>
{users?.title_song?.map((title_song) => (
<li key={title_song}>{title_song}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("movie_year")}>Movie Year</Button>
{users && (
<ul>
{users?.movie_year?.map((movie_year) => (
<li key={movie_year}>{movie_year}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchMovieData("Sean Connery")}>
Sean Connery's List of Movies
</Button>
{movies && (
// console.log(movies),
<ul>
{movies?.["Sean Connery"]?.map((movie) => (
// console.log(movie),
<li key={movie}>{movie}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchMovieData("Roger Moore")}>
Roger Moore List of Movies
</Button>
{movies && (
<ul>
{movies?.["Roger Moore"]?.map((movie) => (
// console.log(moviesR),
<li key={movie}>{movie}</li>
))}
</ul>
)}
</div>
</div>
);
}
export default ButtonClick;
This is so because you are using single state, movies to show movies under both sections.
<ul>
{movies?.map((movie) => (
// console.log(moviesR),
<li key={movie}>{movie}</li>
))}
</ul>
This is common to both sections, and this only checks whether movies have any value or not.
This issue can be solved by creating different states for different movie collections.
One way of handling this is to take a reducer approach:
const [movies, setMovies] = useState({});
const fetchMovieData = (name) => {
axios
.get(
"..."
).then(response => {
...
const newMoviesState = {...movies};
newMoviesState[name] = response.data.filter(item => item.bond_actor === name).map(item => item.movie_title)
setMovies(newMoviesState);
...
})
};
Then, in your JSX for the buttons and lists:
<div>
<Button onClick={() => fetchMovieData("Sean Connery")}>Sean Connery's List of Movies</Button>
{movies["Sean Connery"]?.length && (
...
<ul>
{movies["Sean Connery"].map((movie) => (
...
<li key={movie}>{movie}</li>
))}
</ul>
)
}
</div>
found a simple way to do it.
import React, { useState } from "react";
import styled from "styled-components";
import axios from "axios";
const Button = styled.button`
background-color: black;
color: white;
font-size: 20px;
padding: 10px 60px;
border-radius: 5px;
margin: 10px 0px;
cursor: pointer;
`;
function ButtonClick() {
const [users, setUsers] = useState();
const fetchData = (type) => {
axios
.get(
"https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies"
)
.then((response) => {
console.log(response.data)
const mappedArray = response.data
.map(
(item) =>
item[type] ||
(type === "directors" && item.director) ||
(type === "title_song" && item.title_song) ||
(type === "movie_year" && item.movie_year)
)
.filter((uniqueVal) => uniqueVal);
setUsers({ [type]: Array.from([...new Set(mappedArray)]) });
// console.log(movies)
});
};
const [movies, setMovies] = useState({sean:[], roger: []});
const fetchMovieData = (name, key) => {
axios
.get(
"https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies"
).then(response => {
console.log(response.data)
setMovies({...movies,[key]:response.data.filter(item => item.bond_actor === name).map(item => item.movie_title)});
console.log("Hello World")
console.log("Hello World")
console.log(movies)
})
};
return (
<div>
<div>
<h2>Bond Database</h2>
<h5>
Click on the buttons to see the list of all the bond movie's
directors, bond actors, release year, and title songs
</h5>
<Button onClick={() => fetchData("bond_actor")}>Bond Actors</Button>
{users && (
<ul>
{users?.bond_actor?.map((user, index) => (
<li key={index}>
<a href="https://iznfqs92n3.execute-api.us-west-1.amazonaws.com/dev/api/v2/movies">
{user}
</a>
</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("directors")}>Directors</Button>
{users && (
<ul>
{users?.directors?.map((director) => (
<li key={director}>{director}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("title_song")}>Songs</Button>
{users && (
<ul>
{users?.title_song?.map((title_song) => (
<li key={title_song}>{title_song}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchData("movie_year")}>Movie Year</Button>
{users && (
<ul>
{users?.movie_year?.map((movie_year) => (
<li key={movie_year}>{movie_year}</li>
))}
</ul>
)}
</div>
<div>
<Button onClick={() => fetchMovieData("Sean Connery", "sean")}>Sean Connery's List of Movies</Button>
{movies && movies.sean && (
// console.log(movies),
<ul>
{movies?.sean?.map((movie) => (
// console.log(movie),
<li key={movie}>{movie}</li>
))}
</ul>
)
}
</div>
<div>
<Button onClick={() => fetchMovieData("Roger Moore", "roger")}>Roger Moore List of Movies</Button>
{movies && movies.roger && (
<ul>
{movies?.roger?.map((movie) => (
// console.log(moviesR),
<li key={movie}>{movie}</li>
))}
</ul>
)}
</div>
</div>
);
}
export default ButtonClick;
you can simply pass a key and make sub arrays for each actor
if u can use key map object it will be less confusing.
ex:
const actors = {
sean: "Sean Connery",
roger: "Roger Moore"
}
I'm building a page with two tabs. When one tab is clicked, the other tab should have the className="nav-link active" and the other tab should switch to className="nav-link" and vice-versa.
Here's my code:
import react from 'react'
const account = () => {
const [activeTab, tabActive] = react.useState("true")
return (
<>
<div className='container my-5'>
<ul className="nav nav-tabs">
<li className="nav-item">
<button type="button" className={"nav-link " + (activeTab?'active':'')} onClick={() => tabActive("true")}>Profile details</button>
</li>
<li className="nav-item">
<button type="button" className={"nav-link " + (activeTab?'':'active')} onClick={() => tabActive("false")}>Select Colleges</button>
</li>
</ul>
</div>
<div className='container my-5'>
{
activeTab === "true" && <p>Value is true</p>
}
{
activeTab === "false" && <p>Value is false</p>
}
</div>
</>
)
}
export default account
The aforementioned code should be able to do what I expect, however, I can't get the active class removed and added to the buttons as expected. It's either being applied to both buttons at the same time or two none at all.
Non-empty strings are always truthy. Use booleans instead.
const account = () => {
const [activeTab, tabActive] = react.useState(true);
return (
<>
<div className='container my-5'>
<ul className="nav nav-tabs">
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab ? 'active' : '')}
onClick={() => tabActive(true)}
>
Profile details
</button>
</li>
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab ? '' : 'active')}
onClick={() => tabActive(false)}
>
Select Colleges
</button>
</li>
</ul>
</div>
<div className='container my-5'>
{activeTab ? <p>Value is true</p> : <p>Value is false</p>}
</div>
</>
)
};
Update
For more than 2 tabs use an index or GUID, anything that uniquely identifies a tab, to store in state for the active tab, and check this value for matching when rendering.
Example:
const account = () => {
const [activeTab, tabActive] = react.useState(0);
return (
<>
<div className='container my-5'>
<ul className="nav nav-tabs">
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab === 0 && 'active')}
onClick={() => tabActive(0)}
>
Profile details
</button>
</li>
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab === 1 && 'active')}
onClick={() => tabActive(1)}
>
Select Colleges
</button>
</li>
<li className="nav-item">
<button
type="button"
className={"nav-link " + (activeTab === 2 && 'active')}
onClick={() => tabActive(2)}
>
Select Something Else
</button>
</li>
</ul>
</div>
<div className='container my-5'>
{activeTab === 0 && <p>Active tab is 0</p>}
{activeTab === 1 && <p>Active tab is 1</p>}
{activeTab === 2 && <p>Active tab is 2</p>}
</div>
</>
)
};
I have header component, where I want to toggle className between all the elements of menu (if one of the elements of menu is active and user is clicking to another element - this element become active and all others no). I have a code like this
import React, { useState } from 'react';
import './header.scss';
export const Header = ({ favoriteCount }) => {
const [activeIndex, setActiveIndex] = useState(0);
function toggleClass(index) {
setActiveIndex(index);
}
return (
<header className="header">
<div className="container header-container">
<ul className="header-menu">
<li>
<a
className={
activeIndex === 0
? 'header-menu__link active'
: 'header-menu__link'
}
onClick={() => {
toggleClass(0);
}}
href="##"
>
Characters
</a>
</li>
<li>
<a
className={
activeIndex === 1
? 'header-menu__link active'
: 'header-menu__link'
}
onClick={() => {
toggleClass(0);
}}
href="##"
>
Favorites
</a>
</li>
</ul>
<div className="header-favorite-count">
<i className="far fa-heart"></i>
{favoriteCount}
</div>
</div>
</header>
);
};
and styles to visualise toggling classes
&-menu__link {
color: lightgray;
}
.active {
color: #fff;
}
This approach is working but looks creepy. Maybe somebody knows how to optimize it?
I wouldn't use the index, I'd use the text of the item. I'd also include that text in the href so that there's an indication of what the anchor leads to. To avoid repeated code, you might put the menu items in a reusable array, something like this:
const menuItems = [
"Characters",
"Favorites",
];
export const Header = ({ favoriteCount }) => {
const [activeItem, setActiveItem] = useState("");
const setActiveItem = useCallback((event) => {
setActiveItem(event.currentTarget.href.substring(2));
}, []);
const list = menuItems.map(item =>
<li key={item}>
<a
className={`header-menu__link ${item === activeItem ? "active" : ""}`}
onClick={setActiveItem}
href={"##" + item}>
{item}
</a>
</li>
);
return (
<header className="header">
<div className="container header-container">
<ul className="header-menu">
{list}}
</ul>
<div className="header-favorite-count">
<i className="far fa-heart"></i>
{favoriteCount}
</div>
</div>
</header>
);
};
I am working on my first react project and I got a bit stuck.
I am trying to create a navigation menu where when you click, for example, "men", a dropdown appears.
The issue I am having is that there shall only be one of these dropdowns showing at the same time, I have a total of 6 dropdowns.
I have been trying to remove the class from the elements and then re-adding it, but the issue is that it toggles the class back.
Here is the code:
const BottomNavigation = (props) => {
const [menShowing, setMenShowing] = useState(false);
const [womenShowing, setWomenShowing] = useState(false);
const [accessoriesShowing, setAccessoriesShowing] = useState(false);
const [shoesShowing, setShoesShowing] = useState(false);
const [faceBodyShowing, setFaceBodyShowing] = useState(false);
const [newInShowing, setNewInShowing] = useState(false);
const menHandler = () => setMenShowing((prevCheck) => !prevCheck);
const womenHandler = () => setWomenShowing((prevCheck) => !prevCheck);
const accessoriesHandler = () =>
setAccessoriesShowing((prevCheck) => !prevCheck);
const shoesHandler = () => setShoesShowing((prevCheck) => !prevCheck);
const faceBodyHandler = () => setFaceBodyShowing((prevCheck) => !prevCheck);
const newInHandler = () => setNewInShowing((prevCheck) => !prevCheck);
return (
<nav>
<div className={classes.bottom_navigation}>
<div className={classes.nav_items_container}>
<ul className={classes.nav_link}>
<li className={`${classes.nav_item}`}>
<p onClick={menHandler}>men</p>
<div
key="men"
className={`${classes.nav_dropdown} ${classes.dropdown__men} ${
menShowing ? classes.dropdown_show : null
}`}
>
<Men />
</div>
</li>
<li className={classes.nav_item}>
<p onClick={womenHandler}>women</p>
<div
key="women"
className={`${classes.nav_dropdown} ${
classes.dropdown__women
} ${womenShowing ? classes.dropdown_show : null} `}
>
<Women />
</div>
</li>
<li className={classes.nav_item}>
<p onClick={accessoriesHandler}>accessories</p>
<div
key="accessories"
className={`${classes.nav_dropdown} ${
classes.dropdown__accessories
} ${accessoriesShowing ? classes.dropdown_show : null} `}
>
<Accessories />
</div>
</li>
<li className={classes.nav_item}>
<p onClick={shoesHandler}>shoes</p>
<div
key="shoes"
className={`${classes.nav_dropdown} ${
classes.dropdown__shoes
} ${shoesShowing ? classes.dropdown_show : null} `}
>
<Shoes />
</div>
</li>
<li className={classes.nav_item}>
<p onClick={faceBodyHandler}>face + body</p>
<div
key="facebody"
className={`${classes.nav_dropdown} ${
classes.dropdown__facebody
} ${faceBodyShowing ? classes.dropdown_show : null} `}
>
<FaceBody />
</div>
</li>
<li className={classes.nav_item}>
<p onClick={newInHandler}>new in</p>
<div
key="newin"
className={`${classes.nav_dropdown} ${
classes.dropdown__newin
} ${newInShowing ? classes.dropdown_show : null} `}
>
<NewIn />
</div>
</li>
</ul>
</div>
<div className={classes.options_container}>
<div className={classes.icon_container}>
<span className={classes.cart_sum}>$0.00</span>
<Cart className={classes.icon} />
</div>
<div className={classes.icon_container}>
<Heart className={classes.icon} />
</div>
<div className={classes.icon_container}>
<Visibility className={classes.icon} />
</div>
<div className={classes.icon_container}>
<User className={classes.icon} />
</div>
</div>
</div>
</nav>
);
};
If any other component is needed to solve this issue, let me know!
Instead of keeping every item's showing state in different useState's, you can use a single useState and a single menu click handler like:
const [showItem, setShowItem] = useState(null);
const menuClickHandler = (param) => {
if (showItem === param) {
setShowItem(null);
} else {
setShowItem(param);
}
};
and in your nav items you can call menu click handler and you can check if the current state is the name of current item like:
<li className={`${classes.nav_item}`}>
<p onClick={() => menuClickHandler("men")}>men</p>
<div
key="men"
className={`${classes.nav_dropdown} ${classes.dropdown__men} ${
showItem === "men" ? classes.dropdown_show : null
}`}
>
<Men />
</div>
</li>
You can take a look at this sandbox for this usage.
I highly recommend solving this by making a new component that you can reuse. I'll call mine Dropdown. This takes advantage of React's use of state. We want each dropdown to control it's own state of being open or not. Changing classes works, but I don't think you're properly leveraging what React can do.
Here's my quick version of a Dropdown, which you can test out here. The tech I use here is mostly React Hooks.
import "./dropdown.css";
import React, { useCallback, useEffect, useRef, useState } from "react";
const Dropdown = ({ onOpen, label, children }) => {
const [isOpen, setIsOpen] = useState(false);
const containerRef = useRef();
const onMouseDown = useCallback(
(e) => {
if (containerRef.current && !containerRef.current.contains(e.target)) {
setIsOpen(false);
}
},
[containerRef, setIsOpen]
);
useEffect(() => {
if (isOpen) {
onOpen();
}
}, [isOpen, onOpen]);
useEffect(() => {
window.addEventListener("mousedown", onMouseDown);
return () => window.removeEventListener("mousedown", onMouseDown);
}, [onMouseDown]);
const toggleIsOpen = () => {
setIsOpen(!isOpen);
}
return (
<div ref={containerRef} className="dropdown-container">
<div className="dropdown-label" onClick={toggleIsOpen}>{label}</div>
{isOpen && <div className="dropdown-content">{children}</div>}
</div>
);
};
export default Dropdown;
Here it is in action inside of a simple App.js
import React from "react";
import Dropdown from "./Dropdown.js";
function App() {
return (
<div className="App">
<div className="menu">
<Dropdown
label={<div>Men</div>}
onOpen={() => console.log("Opening men")}
>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
</Dropdown>
<Dropdown
label={<div>Women</div>}
onOpen={() => console.log("Opening women")}
>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
</Dropdown>
<Dropdown
label={<div>Shoes</div>}
onOpen={() => console.log("Opening shoes")}
>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
</Dropdown>
<Dropdown
label={<div>Accessories</div>}
onOpen={() => console.log("Opening accessories")}
>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
<div>Test Menu</div>
</Dropdown>
</div>
</div>
);
}
export default App;
Let me know if you have questions!
I'm using functional component in react js , my onClick function triggers with component rendering without click on my li element ;
this is my parent component that passed the handleCallDetails function as props to child component:
export default function Cartable(){
const [items , setItems] = useState(null);
const [details , setDetails] = useState(null);
function handleCallDetails(id){
if(items !== null && details === null){
let d = items.find(x => {
return x.id === id;
});
}
}
useEffect(() => {
axios.get(`/workflows/${mode}` ,{
params : {
OrganizationId : "FE905B40-DA6E-4A81-8A4F-B447AA6B0EA3" ,
Type : 2 ,
sortorder : "desc" ,
pageIndedx : 1 ,
pageSize : 10
}
}).then(response => {
// console.log('response : ***************** ' , response);
setItems(response.data.data);
}).catch(error => {
console.log('error : ****************** ' , error);
});
} , [mode]);
return (
<Grid container spacing={2}>
<Grid item xs={12} sm={4} md={3}>
<div className="drt_RightSide drt_segment">
<h4 className="drt_RightSideTitle">
<i className="far fa-inbox"></i>
کارتابل
</h4>
<ul>
{/* <li>
<i class="far fa-inbox"></i>
<span>درخواست ها</span>
</li> */}
<li onClick={() => {setMode('pending');}}>
<i className="fas fa-exclamation"></i>
<span><FormattedMessage id="CARTABLE_PENDING" /></span>
<span className="drt_badge_warning drt_NotifNum">5</span>
</li>
<li onClick={() => {setMode('approved');}}>
<i className="far fa-check"></i>
<span>تایید شده</span>
</li>
<li onClick={() => {setMode('rejected');}}>
<i className="far fa-times"></i>
<span>رد شده</span>
<span className="drt_badge_error drt_NotifNum">7</span>
</li>
<li>
<i className="far fa-bell"></i>
<span>خارج از فرآیند</span>
</li>
</ul>
</div>
</Grid>
<Grid item xs={12} sm={8} md={9}>
<div className="drt_LeftSide drt_segment"> */}
{/* cartbale list */}
<CartableList
items={items}
callDetails={handleCallDetails}/>
</div>
</Grid>
</Grid>
);
}
and it is my child compnent that use onClick function that named callDetails:
export default function CartableList(props){
const [showbox , setShowbox] = useState(false);
const [age, setAge] = useState('');
const handleChange = (event) => {
setAge(event.target.value);
};
function handleFilterBox(){
setShowbox(!showbox);
}
return (
<Fragment>
{/* cartable list */}
<div style={{direction : "ltr"}}>
<Scrollbars style={{ height: 400 }}>
{
props.items && props.items !== undefined ?
props.items.map(function(item , index){
return (
<div className="drt_clearfix drt_CartableItem" key={index} onClick={(props.callDetails)(item.id)}>
{/* <div className={clsx(drt_ItemStar , item.star ? drt_IsStared : '')}>
<span><i className={clsx(item.star ? "fas fa-star" : "fal fa-star")}></i></span>
</div> */}
<div className="drt_ItemImg">
<span>
<img alt={userImg} src={item.pictureUrl !== undefined && item.pictureUrl !== null ? item.image : userImg} />
</span>
</div>
<div className={clsx("drt_ItemName" , !item.isSeen ? "drt_IsNotSeen" : '')}>
{item.issuerFirstName}
<br />
{item.issuerLastname}
</div>
<div className="drt_ItemIcon">
<Tooltip title={(props.moduleType)(item.type).name}>
<span className={item.isSeen ? "drt_badge_default" : "drt_badge_primary"}>
<i className={(props.moduleType)(item.type).icon} />
</span>
</Tooltip>
</div>
<div className={clsx("drt_ItemDesc" , !item.isSeen ? "drt_IsNotSeen" : '')}>
{item.objectTitle}
</div>
<div className="drt_ItemStatus">
<span className={(props.stateClass)(item.status)}>
{(props.stateTitle)(item.status)}
</span>
</div>
<div className={clsx("drt_ItemDate" , !item.isSeen ? "drt_IsNotSeen" : '')}>
<p>
<span>
{item.issuerTime}
</span>
<span>
{item.issuerDate}
</span>
</p>
<i className="fal fa-clock" />
</div>
</div>
);
}) : ''
}
</Scrollbars>
</div>
</Fragment>
);
}
please help me to solve this problem without convert my functional component to class component and binding my function
The correct way is this. You need to use arrow function or else react will understand that you want to execute the function at load
wrong
<div className="drt_clearfix drt_CartableItem" key={index} onClick={(props.callDetails)(item.id)}>
correct
<div className="drt_clearfix drt_CartableItem" key={index} onClick={() => props.callDetails(item.id)}>
Change from
onClick={() => {setMode('rejected');}}
to
onClick={() => setMode('rejected')}
Also
<div className="drt_clearfix drt_CartableItem" key={index} onClick={() => props.callDetails(item.id)}>
But where did you define the const [mode, setMode] state
It seems you exec your callback function immediately as it renders based on your code:
onClick={(props.callDetails)(item.id)}
It's supposed to be:
onClick={() => props.callDetails(item.id)}
Is that the issue?
It's mainly because of piece of code onClick={(props.callDetails)(item.id)} in your child component. This code is actually executing callDetails function and passing the item.id value immediately. One way to handle this is to wrap your function.
onClick={() => {props.callDetails(item.id)}}
A simple reason as to why onClick is not called when it is wrapped is because it is not directly passing in any value when initialised.