P粉4410764052023-08-31 15:23:23
您可以使用Redux
。
openAllAccordions
,循環遍歷ID,並將屬於該ID的手風琴設定為open=truecloseAllAccordions
,循環遍歷ID,並將屬於該ID的手風琴設定為open=falseP粉8091101292023-08-31 12:37:09
在一個更或多或少任意的元件實例集合中,需要一些協調是很常見的。我成功使用的一種方法是建立一個與關聯鉤子的Context,元件可以使用該鉤子進行註冊。此鉤子傳回共享狀態的視圖和修改該狀態的函數,以滿足您的需求。
在這裡,您可以建立一個儲存每個已註冊元件的opener
函數並提供openAll
/closeAll
函數的Context:
const AccordionProvider = ({ children }) => { const [openers] = useState(new Set()); // 当创建时,是否应该展开新的可折叠项? //(支持递归展开是必要的) const [defaultOpen, setDefaultOpen] = useState(false); const register = useCallback( (opener) => { openers.add(opener); return () => openers.delete(opener); // 返回一个用于`useEffect`的取消注册函数 }, [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 }; };
還有一個用於執行批次操作的獨立鉤子也很方便:
const useAccordionAsManager = () => { const { openAll, closeAll } = useContext(AccordionContext); return { openAll, closeAll }; };
#請注意,為簡單起見,這裡只是使用了單獨的opener
(又稱setOpen
)函數作為每個已註冊元件的唯一識別碼。一個靈活的替代方案是使用其他標識符,這樣您可以在導航等情況下打開/關閉任意的手風琴。