toggle classname according to click - reactjs

I want to toggle active classname to particular month clicked and january should be bydefault active and these months are mapping from array
<div className="first6-months"> {Data[5].firstsixmonths.map((item, key) => ( <p className={item === "January" ? "jan" : "feb"} // onClick={(event) => handleClick(event, key)} > {item} </p> ))} </div>

If you want to set an "active" class to the selected item that how I would do it:
const [months, setMonths] = useState('January')
const handleChange = (event) => {
setMonths(event.target.name)
}
return (
<div className="first6-months">
{Data[5].firstsixmonths.map((item, key) => (
<p className={item === month ? "active" : ""}
onClick={handleChange}
name={item}>
{item}
</p>
))}
</div>
)

When looping output, always put a key prop on your element
{Data[5].firstsixmonths.map((item, key) => ( <p key={item} onClick={() => handleClick(key)} > {item} </p> ))}
Use some bit of state to track which month is active
const [activeItem, setActiveItem] = useState(0);
const handleClick = (key) = setActiveItem(key);
Then set your className based upon active
import classnames from `classnames`;
//...
<p className={classnames({
active: item === Data[5].firstsixmonths[activeItem]
})} onClick={() => handleClick(key)}>{item}</p>
This is the basics of what you need, but you'll probably need to play with it a little.

Related

All my sidebar menu opens at once in ReactJS

I am trying to create a sidebar menu with dropdwon
For I single menu it works fine but if I have multiple dropdown
All opens at one when I click on the menu to open the submenu.
I am getting the data for the menu from a json array
const SidebarItems = ({ items }) => {
const [open, setOpen] = useState(false)
return (
<div>
{items && items.map((item, index) => {
return (
<div key={index}>
<div>
<li >
<div className="nav-items" onClick={() => setOpen(!open)}>
<span>
<i className="bi-badge-vr" />
{item.title}
</span>
<i className="bi-chevron-down" />
</div>
</li>
</div>
<div className={open ? 'sub-menu sub-menu-open' : "sub-menu"} >
{item.chidren && item.chidren.map((sub_menu, sub_index) => {
return (
<div key={sub_menu}>
<Link to="manager/staff/create">
<span>
<i className="bi-badge-vr" />
{sub_menu.title}
</span>
</Link>
</div>
)
})}
</div>
</div>
)
})}
</div>
)
}
This is because they all use the same state.
Move the item to its own component so I can keep its own state:
const Item = ({ item }) => {
const [open, setOpen] = useState(false);
return <Your item code here />;
};
And in SideBarItems:
items.map((item, index) => {
return <Item item={item} key={index} />;
});

How can I add item on localStroge through ReactJS

I don't understand how I can add an item on localStroge with the handle change method in react js.
The problem is I want to add a favorite list. When I click the favorite list all checkbox fill I need to control them.
I want to store the filled item in my local storage. handlechange function fill all favorite icon why?
Every click will be a single item fill. Is it possible to Material UI or Martial UI checkBox icon? How can I handle it?
Here is my UI view
function Main() {
// Here is my state define
const [checked, setChecked] = React.useState(
localStorage.getItem("love") === "true"
);
const handleChange = (e) => {
localStorage.setItem("love", `${e.target.checked}`);
setChecked(e.target.checked);
console.log(e.target.checked);
};
return (
<>
<div className="row mt-5">
{isLoading ? (
<>
{Array.from({ length }).map((_, i) => (
<MainLoading key={i} />
))}
</>
) : error ? (
<p>Error occured</p>
) : (
<>
{data?.map((product) => (
<div className="col-md-3 mb-5 text-center" key={product.id}>
<img
className="w-100"
style={{ height: "200px", objectFit: "contain" }}
src={product.image}
alt=""
/>
<div>{product.title.substring(0, 20)}</div>
<button
onClick={() => handelAddTocard(product)}
className="mt-3"
>
Add to card
</button>
<button>
<Link
to={`/details/${product.id}`}
className="mt-3 text-decoration-none text-black"
>
view details
</Link>
</button>
{/* How can i control evey single item */}
<Checkbox
checked={checked}
onChange={handleChange}
icon={<FavoriteBorder />}
checkedIcon={<Favorite />}
/>
</div>
))}
</>
)}
</div>
</>
);
}
export default Main;
The problem is that you are using a boolean and you have no way to identify a specific item.
If you want to favorite multiple items, I would use something like this:
const [checked, setChecked] = React.useState(
JSON.parse(localStorage.getItem("loveIds") || "[]")
);
const handleCheck = (id, productChecked) => {
const newItems = productChecked ? [...checked, id] : checked.filter(x => x !== id);
localStorage.setItem("loveIds", JSON.stringify(newItemS));
setChecked(newItems);
console.log(newItems);
};
// ...
<Checkbox
checked={checked}
onChange={(e) => handleCheck(product.id, e.target.checked)}
icon={<FavoriteBorder />}
checkedIcon={<Favorite />}
/>

How to use the key (defined from lists items key) as prop on my Modal

I have defined the Key in my code key={item.id} when mapping through reposit list and I am trying to use it as a prop in my here {openModal && <Modal repo={reposit} my_key={key} setOpenModal={setOpenModal}/> } but it doesn't seems to work. Someone can explain to me how can I access to the key on my Modal by using it as a prop ?
Here is the part of the code :
<List.Item>
<List.Content>
{reposit.map((item) => (
<li key={item.id} onClick={() => {setOpenModal(true)}}>
<i className="folder icon" /> {item.name}
</li>
))}
{openModal && <Modal repo={reposit} my_key={key} setOpenModal={setOpenModal}/> }
</List.Content>
</List.Item>
Thank you for your help.
You have to use state to keep track the key for the clicked list item like below:
import React, { useState } from "react";
const App = () => {
const [myKey, setMyKey] = useState();
return (
<List.Item>
<List.Content>
{reposit.map((item) => (
<li
key={item.id}
onClick={() => {
setMyKey(item.id);
setOpenModal(true);
}}
>
<i className="folder icon" /> {item.name}
</li>
))}
{openModal && (
<Modal repo={reposit} myKey={myKey} setOpenModal={setOpenModal} />
)}
</List.Content>
</List.Item>
);
};
The li key attribute is only defined within the li element, it is not accessible outside of it. Your modal is not a child of the li element so it can't be accessed in the way you are trying. You have to pass item.id to the modal through the li onClick function. One way would be to create state to keep track of what key should be passed to the modal, and change it within the onclick function.
const [modalKey, setModalKey] = useState()
const openModal = (key) => {
setModalKey(key)
setOpenModal(true)
}
...
<List.Item>
<List.Content>
{reposit.map((item) => (
<li key={item.id} onClick={() => openModal(item.id)}>
<i className="folder icon" /> {item.name}
</li>
))}
{openModal && <Modal repo={reposit} my_key={modalKey} setOpenModal={setOpenModal}/> }
</List.Content>
</List.Item>

how to call ".hidden.bs.dropdown" event using jquery inside react function component

I have a multi select dropdown. I am trying to call a function on dropdown close with all selected values but selected items are always empty.
const [selectedItems, setSelectedItems] = useState([]);
const dropdownRef = useRef(null);
useEffect(() => {
if(!isDropdownLoading)
$(dropdownRef.current).on("hidden.bs.dropdown", e => {
onDropdownClose(selectedItems);
//This function is getting called on dropdown close but selectedItems is always empty array.
});
}
}, [isDropdownLoading]);
const toggleItem=(event,selectedItem)=>{
//here logic to find selected items and update state
setSelectedItems(ArrayWithSelectedItems);
}
if (isDropdownLoading) {
return <p className="drop-down-onloading">Loading...</p>;
}
return (
<div ref={dropdownRef}>
<button
type="button"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false"
title={titleText}
>
{name}
</button>
<div className="dropdown-menu">
{dropDownList.map(item => {
if (item.isVisible) {
return (
<button
className="dropdown-item"
onClick={e => toggleItem(e, item)}
key={item.id}
id={name}
>
<i
className={`${
item.isChecked
? "check-box"
: "empty-box"
}`}
></i>
{item.name}
</button>
);
}
})}
</div>
</div>
);
Why state is always empty array inside Jquery event. This is a function based react component.

Using react-multi-carousel but unable to use custom dots

How I can get clickable custom dots of this carousel.
I cannot bind a click event in the list item to move the carousel. I need a proper implementation between onClick and the li item to click on prev and next items in carousel
Here is the full code in the link codebox
const CustomDot = ({onMove,index,onClick,active}) => {
return (
<ol class="carousel-indicators">
<li data-target="#main-slide" data-slide-to="0" className={active ? "active" : "inactive"}
>How t bind the click event list item
onClick={() => onClick()}>{React.Children.slide1}</li>
<li data-target="#main-slide" data-slide-to="1" className={active ? "active" : "inactive"}
onClick={() => onClick()}>{React.Children.slide2} </li>
<li data-target="#main-slide" data-slide-to="2" className={active ? "active" : "inactive"}
onClick={() => onClick()}>{React.Children.slide3} </li>
</ol>
);
};
The problem is that the plugin expects to receive a single element (li for example) as CusomtDot but you pass a list (ol with some children).
The solution, pass a single element, like this:
const CustomDot = ({ onMove, index, onClick, active }) => {
// onMove means if dragging or swiping in progress.
// active is provided by this lib for checking if the item is active or not.
return (
<li
className={active ? "active" : "inactive"}
onClick={() => onClick()}
>
{index + 1}
</li>
);
};
Working demo: https://codesandbox.io/s/react-multi-carousel-customdot-jwkfo
const CustomDot = ({ onMove, index, onClick, active }) => {
return (
<li
className={active ? "active" : "inactive"}
onClick={() => onClick()}
>
<MaximizeIcon />
</li>
);
};
const arrowStyle = {
background: "transparent",
border: 0,
color: "#fff",
fontSize: "80px"
};
const CustomRight = ({ onClick }) => (
<button className="arrow right" onClick={onClick} style={arrowStyle}>
<ArrowForwardIcon style={{ fontSize: "50px" }} />
</button>
);
const CustomLeft = ({ onClick }) => (
<button className="arrow left" onClick={onClick} style={arrowStyle}>
<ArrowBackIcon style={{ fontSize: "50px" }} />
</button>
);
Working demo : https://codesandbox.io/s/react-multi-carousel-customdot-3q0f4?file=/src/App.js:683-1052

Resources