您可以使用Redux
。
openAllAccordions
,循環(huán)遍歷ID,並將屬於該ID的手風(fēng)琴設(shè)定為open=truecloseAllAccordions
,循環(huán)遍歷ID,並將屬於該ID的手風(fēng)琴設(shè)定為open=false在一個更或多或少任意的元件實例集合中,需要一些協(xié)調(diào)是很常見的。我成功使用的一種方法是建立一個與關(guān)聯(lián)鉤子的Context,元件可以使用該鉤子進(jìn)行註冊。此鉤子傳回共享狀態(tài)的視圖和修改該狀態(tài)的函數(shù),以滿足您的需求。
在這裡,您可以建立一個儲存每個已註冊元件的opener
函數(shù)並提供openAll
/closeAll
函數(shù)的Context:
const AccordionProvider = ({ children }) => { const [openers] = useState(new Set()); // 當(dāng)創(chuàng)建時,是否應(yīng)該展開新的可折疊項? //(支持遞歸展開是必要的) const [defaultOpen, setDefaultOpen] = useState(false); const register = useCallback( (opener) => { openers.add(opener); return () => openers.delete(opener); // 返回一個用于`useEffect`的取消注冊函數(shù) }, [openers] ); const openAll = useCallback(() => { setDefaultOpen(true); openers.forEach(opener => opener(true)), }, [setDefaultOpen, openers]); const closeAll = useCallback(() => { setDefaultOpen(false); openers.forEach(opener => opener(false)), }, [setDefaultOpen, openers]); return ( <AccordionContext.Provider value={{ register, openAll, closeAll, defaultOpen }} children={children} /> ); };
...還有一個被每個子元件呼叫的鉤子,用於在上下文中註冊,並傳回熟悉的toggle
/open
值:
const useAccordionAsClient = () => { const { register, defaultOpen } = useContext(AccordionContext); const [open, opener] = useState(defaultOpen); const toggle = useCallback(() => opener((open) => !open), [opener]); useEffect(() => register(opener), [register, opener]); return { toggle, open }; };
還有一個用於執(zhí)行批次操作的獨立鉤子也很方便:
const useAccordionAsManager = () => { const { openAll, closeAll } = useContext(AccordionContext); return { openAll, closeAll }; };
#請注意,為簡單起見,這裡只是使用了單獨的opener
(又稱setOpen
)函數(shù)作為每個已註冊元件的唯一識別碼。一個靈活的替代方案是使用其他標(biāo)識符,這樣您可以在導(dǎo)航等情況下打開/關(guān)閉任意的手風(fēng)琴。