面试题答案
一键面试确保组件获取原组件树中的上下文(context)信息
- 使用React.createContext:
- 首先创建上下文对象,例如:
import React from'react'; const MyContext = React.createContext();
- 在原组件树的上层组件中,通过
MyContext.Provider
提供上下文数据:
<MyContext.Provider value={/* 上下文数据 */}> {/* 原组件树 */} <ComponentThatMayUsePortal /> </MyContext.Provider>
- 在使用
React Portal
渲染的组件中,通过MyContext.Consumer
或useContext
钩子来获取上下文数据。 - 使用
MyContext.Consumer
:
import React from'react'; import { MyContext } from './MyContext'; const PortalComponent = () => { return ( <MyContext.Consumer> {context => ( {/* 使用上下文数据 */} <div>{context.someData}</div> )} </MyContext.Consumer> ); }; export default PortalComponent;
- 使用
useContext
钩子(适用于函数式组件):
import React, { useContext } from'react'; import { MyContext } from './MyContext'; const PortalComponent = () => { const context = useContext(MyContext); return ( <div>{context.someData}</div> ); }; export default PortalComponent;
- 传递props:
- 也可以通过在原组件树向使用
Portal
的组件传递props的方式,将上下文相关的数据传递下去。例如:
const ParentComponent = () => { const someData = { /* 上下文相关数据 */ }; return ( <ComponentThatMayUsePortal contextData={someData} /> ); }; const ComponentThatMayUsePortal = ({ contextData }) => { // 在Portal组件中使用contextData return ( //... ); };
- 也可以通过在原组件树向使用
处理事件冒泡使其像在原组件树内一样正常工作
- 事件委托:
- 在原组件树中,事件冒泡是由浏览器的事件机制处理的。当使用
React Portal
将组件渲染到其他位置时,可以通过事件委托来模拟事件冒泡。 - 在Portal渲染的组件内,给需要冒泡事件的元素添加事件监听器,例如:
const PortalComponent = () => { const handleClick = (e) => { // 手动触发父组件中的事件处理函数 const parentElement = document.getElementById('parent - component - id'); if (parentElement) { const newEvent = new MouseEvent('click', { bubbles: true, cancelable: true, view: window }); parentElement.dispatchEvent(newEvent); } }; return ( <div onClick={handleClick}>Click me</div> ); };
- 在原组件树中,事件冒泡是由浏览器的事件机制处理的。当使用
- 使用React事件系统:
- React有自己的合成事件系统,它模拟了原生事件的行为。如果希望利用React的事件系统来处理事件冒泡,可以在原组件树的父组件中添加事件处理函数,然后通过props传递给Portal渲染的组件。
- 例如:
const ParentComponent = () => { const handleClick = () => { // 处理事件 }; return ( <ComponentThatMayUsePortal onCustomClick={handleClick} /> ); }; const ComponentThatMayUsePortal = ({ onCustomClick }) => { return ( <div onClick={onCustomClick}>Click me</div> ); };