Heim > Fragen und Antworten > Hauptteil
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
)函数作为每个已注册组件的唯一标识符。一个灵活的替代方案是使用其他标识符,这样您可以在导航等情况下打开/关闭任意的手风琴。