Open kongshu612 opened 2 years ago
Hy @kongshu612, i think you are missing some props there.
in order to use multiple dropdown, you need to pass the open
props on the component and also you need to maintain the state for all the related dropdown picker accordingly.
So in your case, it should be like
const [open1,setopen1] = useState(false);
const [open2,setOpen2] = useState(false);
const [open3,setOpen3] = useState(false);
<DropDownPicker
multiple={true}
listMode="MODAL"
open={open1} // this one
value={value1}
items={items1}
setOpen={setOpen1}
/>
<DropDownPicker
multiple={true}
listMode="MODAL"
open={open1} // this one
value={value2}
items={items2}
setOpen={setOpen2}
/>
So in your case, you have 4 pickers, you need to maintain the state for 4 different pickers just like above. I hope i am able to answer your issue.Correct me if i failed to understand your issue.
hi @aashishshrestha5532 , thanks for your reply. my case was a little different with what you comment. it make sense to maintain isolated open state for each dropdown in the component level. In my case, these dropdowns live in different components, and those components are composed in one screen. Currently, my workaround is to maintain such open state in the global level, which I think is not good.
If we provide a transparent mask behind the dropdown panel and tap the mask will auto dismiss the dropdown panel, that will be great.
Hi, I have the same problem, did you manage to solve it?
I'm facing the same issue, any workaround?
Hi @MatheusHCP , @durgesh94 ,sorry for reply late. My workaround is to define a global state by using hookAPI. see the code bellow
import React from 'react';
export interface IClose {
close: () => void;
displayName?: string;
}
let modals: Set<IClose> = new Set();
let activeModal: IClose | undefined;
function push(instance: IClose) {
if (!modals.has(instance)) {
modals.add(instance);
}
}
function popup(instance: IClose) {
if (modals.has(instance)) {
modals.delete(instance);
}
if (activeModal === instance) {
activeModal = undefined;
}
}
function toggleOpen(instance: IClose, open: boolean) {
if (open) {
if (activeModal !== instance) {
activeModal?.close();
activeModal = instance;
}
} else {
if (activeModal === instance) {
activeModal = undefined;
}
}
}
export function useAutoClose(instance: IClose) {
React.useEffect(() => {
push(instance);
return () => {
popup(instance);
}
}, [instance]);
return React.useCallback((open: boolean) => {
toggleOpen(instance, open);
}, [instance]);
}
Hi @MatheusHCP , @durgesh94 ,sorry for reply late. My workaround is to define a global state by using hookAPI. see the code bellow
import React from 'react'; export interface IClose { close: () => void; displayName?: string; } let modals: Set<IClose> = new Set(); let activeModal: IClose | undefined; function push(instance: IClose) { if (!modals.has(instance)) { modals.add(instance); } } function popup(instance: IClose) { if (modals.has(instance)) { modals.delete(instance); } if (activeModal === instance) { activeModal = undefined; } } function toggleOpen(instance: IClose, open: boolean) { if (open) { if (activeModal !== instance) { activeModal?.close(); activeModal = instance; } } else { if (activeModal === instance) { activeModal = undefined; } } } export function useAutoClose(instance: IClose) { React.useEffect(() => { push(instance); return () => { popup(instance); } }, [instance]); return React.useCallback((open: boolean) => { toggleOpen(instance, open); }, [instance]); }
i'm not sure why you have a modals set and all those extra functions but this worked for me:
import React, { SetStateAction } from "react";
export interface IClose {
setOpen: (value: boolean) => void;
id: string;
}
let activeDropdown: IClose | undefined;
function toggleOpen(instance: IClose, open: SetStateAction<boolean>) {
if (open) {
if (activeDropdown !== instance) {
activeDropdown?.setOpen(false);
activeDropdown = instance;
}
instance.setOpen(true);
} else {
if (activeDropdown === instance) {
activeDropdown = undefined;
}
instance?.setOpen(false);
}
}
export function closeActiveDropdown() {
activeDropdown?.setOpen(false);
activeDropdown = undefined;
}
export function useAutoCloseDropdown(instance: IClose) {
return React.useCallback(
(open: SetStateAction<boolean>) => {
toggleOpen(instance, open);
},
[instance]
);
}
In the component where I render the dropdown:
const [open, setOpen] = useState(false);
const toggle = useAutoCloseDropdown({ id: label, setOpen });
Then simply pass toggle
to the setOpen
prop of DropdownPicker
For future coders with the same problem: you can also wrap your page in a <TouchableWithoutFeedback>
and set the onPress
to the globally exported closeActiveDropdown
so that tapping outside of the dropdown closes it.
And if you want to use this with a ScrollView
inside, it's gonna disable the scrolling, so add an enclosing View
inside your ScrollView
and add this prop to it: onStartShouldSetResponder={() => true}
(from StackoverFlow)
Hi @MatheusHCP , @durgesh94 ,sorry for reply late. My workaround is to define a global state by using hookAPI. see the code bellow
import React from 'react'; export interface IClose { close: () => void; displayName?: string; } let modals: Set<IClose> = new Set(); let activeModal: IClose | undefined; function push(instance: IClose) { if (!modals.has(instance)) { modals.add(instance); } } function popup(instance: IClose) { if (modals.has(instance)) { modals.delete(instance); } if (activeModal === instance) { activeModal = undefined; } } function toggleOpen(instance: IClose, open: boolean) { if (open) { if (activeModal !== instance) { activeModal?.close(); activeModal = instance; } } else { if (activeModal === instance) { activeModal = undefined; } } } export function useAutoClose(instance: IClose) { React.useEffect(() => { push(instance); return () => { popup(instance); } }, [instance]); return React.useCallback((open: boolean) => { toggleOpen(instance, open); }, [instance]); }
i'm not sure why you have a modals set and all those extra functions but this worked for me:
import React, { SetStateAction } from "react"; export interface IClose { setOpen: (value: boolean) => void; id: string; } let activeDropdown: IClose | undefined; function toggleOpen(instance: IClose, open: SetStateAction<boolean>) { if (open) { if (activeDropdown !== instance) { activeDropdown?.setOpen(false); activeDropdown = instance; } instance.setOpen(true); } else { if (activeDropdown === instance) { activeDropdown = undefined; } instance?.setOpen(false); } } export function closeActiveDropdown() { activeDropdown?.setOpen(false); activeDropdown = undefined; } export function useAutoCloseDropdown(instance: IClose) { return React.useCallback( (open: SetStateAction<boolean>) => { toggleOpen(instance, open); }, [instance] ); }
In the component where I render the dropdown:
const [open, setOpen] = useState(false); const toggle = useAutoCloseDropdown({ id: label, setOpen });
Then simply pass
toggle
to thesetOpen
prop ofDropdownPicker
For future coders with the same problem: you can also wrap your page in a
<TouchableWithoutFeedback>
and set theonPress
to the globally exportedcloseActiveDropdown
so that tapping outside of the dropdown closes it.And if you want to use this with a
ScrollView
inside, it's gonna disable the scrolling, so add an enclosingView
inside yourScrollView
and add this prop to it:onStartShouldSetResponder={() => true}
(from StackoverFlow)
this helps thank you !
Hi, Assume we have the multiple dropdown aligned in the vertical one by one. the multi dropdowns can be opened at the same time. If we provide a auto dimiss feature when user tap out of dropdown panel, that will be great.
currently, we use a global hook to auto dismiss the opened dropdown to bypass this issue.