I am trying to lean react by solving a problem in react. Providing the react code challenge below.
I am trying to close the drop down when I click outside. I tried to debug but no luck.
Can you guys give comments for the code toolbar, its hard to understand the video for each functionality.
I googled spread, use ref but not sure why he is using spread too
I googled but still no luck, not sure how to solve it. Providing my code below and stackblitz. Can you guys help me.
https://www.youtube.com/watch?v=V2zEAXLQbF4&list=PL6x5Q-Sj_Bla3_wMqhETxMBjFml0XJNPI&index=11
import { useEffect, useRef, useState } from 'react';
import './stateDropdown.css';
import { states } from './States';
export function StateDropdown() {
const [isDropDownDisplayed, setIsDropdowndisplayed] = useState(false);
const [selectedStates, setSelectedStates] = useState<Record<string, boolean>>(
states.reduce((obj, state) => ({ ...obj, [state.abbreviation]: false }), {})
);
const numberOfStatesSelected =
Object.values(selectedStates).filter(Boolean).length;
const dropDownRef = useRef(null);
useEffect(() => {
const onClick = (e: any) => {
if (e.target !== dropDownRef.current) {
console.log('we are here');
setIsDropdowndisplayed(false);
}
};
document.addEventListener('click', () => {});
// clean up
return () => {
document.removeEventListener('click', onClick);
};
}, []);
return (
<fieldset className="state-dropdown">
<button
className=""
onClick={(e) => {
e.stopPropagation();
setIsDropdowndisplayed((prevState) => !prevState);
}}
>
{numberOfStatesSelected > 0
? `${numberOfStatesSelected} states selected`
: '-- Select your states --'}
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
className="w-6 h-6"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M6 13.5V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m12-3V3.75m0 9.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 3.75V16.5m-6-9V3.75m0 3.75a1.5 1.5 0 010 3m0-3a1.5 1.5 0 000 3m0 9.75V10.5"
/>
</svg>
</button>
{isDropDownDisplayed && (
<div
onClick={(e) => {
e.stopPropagation();
}}
ref={dropDownRef}
className="panel"
>
{states.map((state) => (
<fieldset
key={state.abbreviation}
className={selectedStates[state.abbreviation] ? `selected` : ''}
>
<input
onChange={(e) =>
setSelectedStates({
...selectedStates,
[state.abbreviation]: e.target.checked,
})
}
checked={selectedStates[state.abbreviation]}
id={`input-${state.abbreviation}`}
type="checkbox"
/>
<label htmlFor={`input-${state.abbreviation}`}>
{state.name}
</label>
</fieldset>
))}
</div>
)}
</fieldset>
);
}
2
Answers
To make the menu close if you click outside of the menu you just need to update
document.addEventListener('click', () => {});
to
document.addEventListener('click', onClick);
Currently you are creating an event listener that is not doing anything but we need it to trigger your onClick to check if the click was within the menu or not.
you can use antd dropdown
see here
or you can add an onclick function to the container of the dropdown