首页 > 解决方案 > 了解包装组件的道具

问题描述

我对本教程中以下代码中的导出魔法感到困惑(可在GitHub 上获得):

import React, { Component } from 'react';
import withFirebaseAuth from 'react-with-firebase-auth'
import firebase from 'firebase/app';
import 'firebase/auth';
import firebaseConfig from './firebaseConfig';
import logo from './logo.svg';
import './App.css';

const firebaseApp = firebase.initializeApp(firebaseConfig);

class App extends Component {
  render() {
    
    const {
      user,
      signOut,
      signInWithGoogle,
    } = this.props;

    if (user) {
      console.log(user.uid);
    }

    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          {
            user
              ? <p>Hello, {user.displayName}</p>
              : <p>Please sign in.</p>
          }

          {
            user
              ? <button onClick={signOut}>Sign out</button>
              : <button onClick={signInWithGoogle}>Sign in with Google</button>
          }
        </header>
      </div>
    );
  }
}

const firebaseAppAuth = firebaseApp.auth();

const providers = {
  googleProvider: new firebase.auth.GoogleAuthProvider(),
};

export default withFirebaseAuth({
  providers,
  firebaseAppAuth,
})(App);

我不明白(1)为什么App.props有新成员和(2)为什么这些新成员在.开头不是未定义的App.render()。更详细地说:

  1. 根据文档,我知道对withFireBaseAuth()in的调用会export返回一个函数,该函数在App作为参数调用时会返回一个组件。但是,它是一个新组件。那么,怎么会props被加到App呢?
  2. 的调用withFireBaseAuth()出现的定义之后App,那么在 中使用的时候怎么App.props.user不是 undefinedApp.render()呢?

标签: javascriptreactjsfirebase

解决方案


  1. 根据文档,我知道在 export 中调用 withFireBaseAuth() 会返回一个函数,当使用 App 作为参数调用该函数时,会返回一个组件。但是,它是一个新组件。那么,道具是如何添加到 App 中的呢?

withFirebaseAuth是一个高阶组件,它实际上只是一个专门的高阶函数,它消耗一个 React 组件,赋予它额外的行为(道具等)并返回一个新的组件。

一个非常简单的 HOC 可能如下所示:

const withMyHOC = Component => props => (
  <Component {...props} extraProp="extraProp" />
);

并使用,const MyComponentWithExtraProp = withMyHOC(MyComponent);.

这里的诀窍是 HOC 返回 React 组件,即它们接收props,然后将它们转发(扩展运算符)传递给被装饰的组件。

也可以编写 HOC 来接受额外的参数。

const withMyHOC = (arg1, arg2) => Component => props => {
  useEffect(() => {
    console.log('rendered', arg2);
  });
  return (
    <Component {...props} extraProp="extraProp" arg={arg1} />
  )
};

并使用,const MyComponentWithExtraProp = withMyHOC("test")(MyComponent);.

withFirebaseAuth似乎采用配置参数,创建身份验证提供程序,并将usersignOutsignInWithGoogle作为道具注入正在装饰的组件中,例如App.

  1. 对withFireBaseAuth()的调用出现在App的定义之后,那么App.props.user怎么在App.render()中使用的时候不是undefined呢?

请记住,这些只是组件声明。App组件在文件中声明,然后装饰,withFirebaseAuth然后默认导出。

export default withFirebaseAuth({
  providers,
  firebaseAppAuth,
})(App);

AppReact 默认导入并渲染其他地方(真正的装饰)。

import App from '../path/to/app';

ReactDOM.render(
  <App />,
  document.getElementById("root")
);

请注意,我们不需要传递任何道具,但是user,signOutsignInWithGoogle将由withFirebaseAuth.


推荐阅读