From firebase I fetch data and map this data to be shown in cards, every card has edit component and CardComponent(edit component parent) which use ref provided from useHandleOpen custom hook
Error message:
Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Component where ref is in use
export default function EditCard(id) { const { ref, isOpen, setIsOpen } = useHandleOpen(false); return ( <div> <GoKebabVertical ref={ref} className="cursor-pointer " onClick={() => setIsOpen(true)} /> {isOpen && ( <div ref={ref} className="w-20 h-15 bg-white z-30 rounded-md absolute text-center top-0 right-0 " > <p className="hover:bg-blue-300 hover:text-white cursor-pointer"> Edytuj </p> <p className="bg-red-400 text-white font-semibold hover:bg-red-600 cursor-pointer" onClick={() => {}} > UsuĊ </p> </div> )} </div> ); } export const Edit = memo(EditCard);
Card component which use ref tho and its Edit parent
const Card = ({ data, id }) => { const editRef = useRef(null); const { ref, isOpen, setIsOpen } = useHandleOpen(editRef); return ( <div className="bg-gradient-to-r from-blue-200 to-purple-500 w-64 h-28 rounded-md relative " > <div className="relative top-0 left-0"> <p className="px-2 pt-1 font-bold text-gray-800 text-lg"> {data.subject_name} </p> <p className="px-2 text-xs text-gray-800">Sala 101</p> </div> <div className="absolute top-0 right-0 rounded-r-md rounded-b-none bg-white w-6 h-7 grid place-items-center " > <Edit id={id} /> </div> <div className="absolute bottom-9 left-0 mb-2.5"> <p className="px-2 text-xs text-gray-800">{data.teacher}</p> </div> <div className=" flex direction-row mt-7 text-center w-full justify-end align-bottom pr-2 "> <div className="rounded-lg w-14 h-7 mx-3 bg-purple-300"> <a href={data.link_subject} className="text-gray-800 " target="_blank" rel="noreferrer" > Lekcja </a> </div> <div className="rounded-lg w-14 h-7 bg-gray-800 "> <a href={data.link_online_lesson} target="_blank" rel="noreferrer" className="text-white" > Online </a> </div> </div> <div className=" absolute bottom-0 left-0 rounded-l-md bg-white w-7 h-6 grid place-items-center devide-solid" > {isOpen ? ( <AiOutlineUp className="cursor-pointer" ref={ref} onClick={() => setIsOpen(true)} /> ) : ( <AiOutlineDown className="cursor-pointer" ref={ref} onClick={() => setIsOpen(true)} /> )} </div> {isOpen && ( <div className="bg-gradient-to-r from-blue-200 to-purple-500 w-full text-left rounded-b-md p-4 " ref={ref} > <p className="font-bold text-gray-800 text-sm ">Lekcje w:</p> <p className="text-gray-800 text-sm">PN: 8-12</p> </div> )} </div> ); }; export const CardSubject = memo(Card);
Custom hook with ref:
export default function useHandleOpen() { const [isOpen, setIsOpen] = useState(false); const ref = useRef(null); const handleClickOutside = (event) => { if (ref.current && !ref.current.contains(event.target)) { setIsOpen(!isOpen); } }; useEffect(() => { document.addEventListener("click", handleClickOutside, !isOpen); return () => { document.removeEventListener("click", handleClickOutside, !isOpen); }; }); return { ref, isOpen, setIsOpen }; }
Edit: Tried change it this way, but this displays warning too.
export default function useHandleOpen(ref) { const [isOpen, setIsOpen] = useState(false); const handleClickOutside = (event) => { if (ref.current && !ref.current.contains(event.target)) { setIsOpen(!isOpen); } }; useEffect(() => { document.addEventListener("click", handleClickOutside, !isOpen); return () => { document.removeEventListener("click", handleClickOutside, !isOpen); }; }); return { ref, isOpen, setIsOpen }; }
And use hook like this:
const editRef = useRef(null); const { ref, isOpen, setIsOpen } = useHandleOpen(editRef);
Advertisement
Answer
Ok i fixed it by removing ref from places where i use onClick method for changing the state