Tenho 2 componentes. Uma Navbar e uma Sidebar/Cart. Na Navbar, tenho um botão que abre e fecha a Sidebar. Tenho um evento que aciona a função clickOutside e está funcionando. O problema é que quando clico no item do carrinho quando a sidebar está ativa, a sidebar fecha e reabre novamente.
Meu App.jsx:
import { useEffect, useState } from "react";
import "./App.css";
import { Navbar } from "./Components/Navbar";
import { ListItem } from "./Components/ListItem";
import { Cart } from "./Components/Cart";
function App() {
const [list, setList] = useState([]);
const [cartActive, setCartActive] = useState(false);
const fetchList = () => {
fetch(`https://fakestoreapi.com/products`)
.then((res) => res.json())
.then((data) => {
setList(data);
})
.catch((error) => {});
};
useEffect(() => {
fetchList();
}, []);
return (
<>
<Navbar setCartActive={setCartActive} cartActive={cartActive} />
<Cart cartActive={cartActive} setCartActive={setCartActive} />
<div className="main">
<div className="container">
{list.map((item) => {
return <ListItem key={item.id} item={item} />;
})}
</div>
</div>
</>
);
}
export default App;
Minha barra de navegação:
import { useEffect, useState } from "react";
import { FaShoppingBag } from "react-icons/fa";
import { useSelector } from "react-redux";
export const Navbar = ({ setCartActive, cartActive }) => {
const cart = useSelector((state) => state.cart.cart);
const [totalItems, setTotalItems] = useState(0);
const fetchTotalItems = () => {
setTotalItems(cart.reduce((acc, curr) => acc + curr.amount, 0));
};
useEffect(() => {
fetchTotalItems();
}, [cart]);
return (
<nav>
<div className="container">
<div className="brand">
Redux<span>Store</span>
</div>
<div className="icon" onClick={() => setCartActive(!cartActive)}>
<FaShoppingBag /> ({totalItems})
</div>
</div>
</nav>
);
};
E minha barra lateral/carrinho:
import { useSelector } from "react-redux";
import { CartItem } from "./CartItem";
import { useEffect, useRef } from "react";
export const Cart = ({ cartActive, setCartActive }) => {
const cart = useSelector((state) => state.cart.cart);
const cartRef = useRef();
const handleClickOutside = (e) => {
if (cartActive && cartRef.current && !cartRef.current.contains(e.target)) {
setCartActive(false);
}
};
useEffect(() => {
document.addEventListener("mousedown", handleClickOutside);
() => {
document.removeEventListener("mousedown", handleClickOutside);
};
});
return (
<div className={`cart ${cartActive ? "active" : ""}`} ref={cartRef}>
{cart.map((item) => {
return <CartItem key={item.id} item={item} />;
})}
</div>
);
};
Isso funciona, mas quando o usuário clica no ícone do carrinho quando a barra lateral está aberta, a barra lateral fecha e reabre. Isso ocorre porque ele captura a função clickOutside. Como posso parar essa função clickoutside na barra de navegação?
aqui está um link para codesandbox
O problema é que você está alterando o estado ativo dos componentes Sidebar e Navbar . Então, quando você clica no ícone na navbar, a primeira
handleClickOutside
função é acionada, o que fecha a sidebar e imediatamenteonClick
a função no componente Navbar é acionada, o que a abre.Uma solução rápida é excluir o botão Navbar na
handleClickOutside
função.Verifique esta demonstração do CodeSandbox . Na demonstração, também alterei o
mousedown
evento paraclick
event.