React:子组件如何访问父组件Props?实现手风琴组件交互
可复用React手风琴组件实现方案
要实现点击标题切换内容显示,核心是让父组件Accordion维护展开状态,子组件AccordionTitle和AccordionSummary能共享这个状态。用React Context是最适合的方式——不用手动传递props,子组件可以直接获取父组件的状态和切换方法,同时每个Accordion实例会独立维护自己的状态,互不干扰。
1. 创建Accordion上下文
先定义一个Context,用来传递手风琴的状态和操作方法:
import { createContext, useContext, useState } from 'react'; // 创建上下文 const AccordionContext = createContext();
2. 实现Accordion父组件
父组件负责维护展开状态isOpen,以及切换状态的方法toggleOpen,并通过Context.Provider把这些值传递给子组件:
export function Accordion({ children }) { const [isOpen, setIsOpen] = useState(false); const toggleOpen = () => { setIsOpen(prev => !prev); }; return ( <AccordionContext.Provider value={{ isOpen, toggleOpen }}> <div className="accordion"> {children} </div> </AccordionContext.Provider> ); }
3. 实现AccordionTitle子组件
子组件消费Context,给标题绑定点击事件,调用父组件的toggleOpen方法:
export function AccordionTitle({ children }) { const { toggleOpen } = useContext(AccordionContext); return ( <div className="accordion-title" onClick={toggleOpen} style={{ cursor: 'pointer', padding: '8px', border: '1px solid #eee' }} > {children} </div> ); }
4. 实现AccordionSummary子组件
根据Context里的isOpen状态,决定是否显示内容:
export function AccordionSummary({ children }) { const { isOpen } = useContext(AccordionContext); if (!isOpen) return null; return ( <div className="accordion-summary" style={{ padding: '8px', border: '1px solid #eee', borderTop: 'none' }} > {children} </div> ); }
5. 使用示例
按照你给出的方式使用,多个手风琴实例会独立工作:
function App() { return ( <div> <Accordion> <AccordionTitle>This is an accordion title</AccordionTitle> <AccordionSummary>This is the accordion summary, which will be shown if the user clicks the accordion title</AccordionSummary> </Accordion> <Accordion> <AccordionTitle>Second accordion title</AccordionTitle> <AccordionSummary>Second summary content, independent from the first accordion</AccordionSummary> </Accordion> </div> ); }
补充说明
- 每个
Accordion组件自己维护isOpen状态,所以多个手风琴之间完全独立,点击一个不会影响另一个。 - 用Context的好处是,即使后续子组件嵌套更深,也不用层层传递props,直接消费Context就能拿到状态和方法。
- 可以根据需求扩展,比如默认展开、禁用状态、自定义样式等,只需要在父组件或者子组件里添加对应的逻辑即可。
内容的提问来源于stack exchange,提问作者user3040230424
相关产品推荐
相关产品推荐

