相同的 React.createContext 在功能组件和 React.Components 中是如何工作的

Posted

技术标签:

【中文标题】相同的 React.createContext 在功能组件和 React.Components 中是如何工作的【英文标题】:How does the same React.createContext work in functional components and React.Components 【发布时间】:2021-02-01 06:20:31 【问题描述】:

我学习了 React,现在我做了一些 React.createContext 并有一个问题。我是初学者,所以有一些学习曲线请指教!

我明白,如果我这样做:

import React from 'react';

const FirebaseContext = React.createContext(null);
export const withFirebase = Component => props => (
    <FirebaseContext.Consumer>firebase => <Component ...props firebase=firebase /></FirebaseContext.Consumer>
);
export default FirebaseContext;

我以后可以这样做来定义 Context 应该提供的内容: (在这种情况下,它是处理 Firebase 功能的类)

import Firebase,  FirebaseContext  from './firebase';

ReactDOM.render(
    <FirebaseContext.Provider value=new Firebase()>
        <Provider store=store>
            <App />
        </Provider>
    </FirebaseContext.Provider>,

    document.getElementById('root'),
);

现在我可以像这样使用 Contect,因为它已在上面提供:

class App extends Component 
    componentDidMount() 
        const  firebase  = this.props;
        firebase
            .doSignInAnonymously()
            ...
    

    render() 
        return (
            ....
        );
    


export default App;

我的问题是,如果我在上面的 Apprender 中没有返回 React.Components 而是像你在下面看到的那样返回 function component 怎么办:

render() 
    return (
        <div>
            <Header />
        </div>
    );

标题:

function Header() 
    return (
        <header>
            <Hero />
        </header>
    );

我现在如何使用上面创建的上下文?

我尝试使用上面首先显示的withFirebase,这里又是这样:

export const withFirebase = Component => props => (
    <FirebaseContext.Consumer>firebase => <Component ...props firebase=firebase /></FirebaseContext.Consumer>
);

但如果我将functional Component Header 包装在withFirebase 中,那么我仍然无法使用this.props,因为它们没有this

我想我可以用provider 包装***App 那么孩子们可以通过 props 访问,但不能访问功能组件,或者它是如何工作的?

【问题讨论】:

【参考方案1】:

Header 在您的情况下是一个功能组件,因此您可以通过钩子访问上下文:

import React,  useContext  from 'react'
import FirebaseContext from '..'

function Header() 
    const firebase = useContext(FirebaseContext)
    return (
        <header>
            <Hero />
        </header>
    );


我希望你的 React 版本支持 hooks (v. 16.8)

【讨论】:

谢谢,很高兴知道。我在想那有什么意义,因为我还不如做正常的import firebase from ...,然后我得到相同的聚合类型的关联firebase,对吗?? 正确 - 您也可以在组件中导入 firebase ref。通过firebase ref 传递props/context 让您更轻松地对组件进行单元测试(如果适合您的话),因为您可以用模拟替换服务的实际实现。 感谢好消息。 React 有时会创建一个完全是 Rect.Component 的应用程序或函数式的有点矛盾。此外,Eslint 还奇怪地提出了关于不使用的建议,例如..props 传播或者即使 React.Component 没有 constructor 那么它应该被转换为一个功能组件。然后把东西放在更高的层次上不起作用。感觉 React 生态系统是一个混搭,我来自 android Java c++ .Net 我的建议是放弃基于类的 React 方法,转而使用函数式 API。如果你有 java / c++ 背景,你可能更熟悉面向对象的概念,如classconstructor 等,但基于类的 React 方法可能有一天会消失(其中一些概念,如 componentWillMount已弃用)

以上是关于相同的 React.createContext 在功能组件和 React.Components 中是如何工作的的主要内容,如果未能解决你的问题,请参考以下文章

有啥实用的方法可以在组件中调用“React.createContext()”吗?

“React.createContext 不是函数” - 但我没有使用它

带有 React.createContext 的 Typescript HOC

如何将 React.createContext() 与反应路由器一起使用?

react源码分析/createContext

使用 null 作为初始值时,`React.createContext(null)` 的打字稿类型