如何在父子组件中同时使用Chakra-UI useDisclosure控制子组件isOpen状态
Chakra UI useDisclosure 跨组件控制状态实现方案
结论
该需求完全可以实现,核心思路是状态提升,将useDisclosure hook定义在父子组件的公共父级,按需将状态和方法透传给子组件即可。
实现步骤
基础方案(适合父子组件层级近的场景)
直接把useDisclosure定义在父组件,父组件直接调用onToggle,再把子组件需要的isOpen状态和onClose方法通过props传给子组件。
父组件代码示例
import { useDisclosure, Button } from '@chakra-ui/react' import ChildComponent from './ChildComponent' export default function Parent() { // 状态统一定义在父组件 const { isOpen, onToggle, onClose } = useDisclosure() return ( <> <Button onClick={onToggle}>父组件切换子组件显隐</Button> <ChildComponent isOpen={isOpen} onClose={onClose} /> </> ) }
子组件代码示例
import { Box, Button } from '@chakra-ui/react' export default function Child({ isOpen, onClose }) { // 根据传入的isOpen控制是否渲染内容 if (!isOpen) return null return ( <Box p={5} borderWidth="1px" borderRadius="md"> <p>子组件受控内容</p> <Button onClick={onClose} mt={3}>子组件关闭</Button> </Box> ) }
优化方案(适合多层组件嵌套场景)
如果父子组件之间隔了多层组件,直接透传props会出现props drilling问题,可通过React Context封装状态:
// 1. 创建共享context import { createContext, useContext } from 'react' import { useDisclosure } from '@chakra-ui/react' const DisclosureContext = createContext() export function DisclosureProvider({ children }) { const disclosure = useDisclosure() return ( <DisclosureContext.Provider value={disclosure}> {children} </DisclosureContext.Provider> ) } export const useDisclosureContext = () => useContext(DisclosureContext) // 2. 父组件使用Provider包裹子组件 <DisclosureProvider> <Parent /> <DeepChild /> </DisclosureProvider> // 3. 任意层级的组件都可以调用方法 const { isOpen, onToggle, onClose } = useDisclosureContext()
注意事项
- 不要在父子组件内部分别定义独立的
useDisclosure,两个独立hook的状态没有关联,无法互相控制。 - 如果子组件需要支持复用,可做兼容处理:子组件内部默认使用自己的
useDisclosure,当外部传入isOpen和控制方法时,优先使用外部传入的状态,同时支持受控和非受控两种使用模式。
内容的提问来源于stack exchange,提问作者Moshe
相关产品推荐
相关产品推荐

