javascript - 了解包装组件的道具
问题描述
我对本教程中以下代码中的导出魔法感到困惑(可在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()
。更详细地说:
- 根据文档,我知道对
withFireBaseAuth()
in的调用会export
返回一个函数,该函数在App
作为参数调用时会返回一个组件。但是,它是一个新组件。那么,怎么会props
被加到App
呢? - 的调用
withFireBaseAuth()
出现在的定义之后App
,那么在 中使用的时候怎么App.props.user
不是 undefinedApp.render()
呢?
解决方案
- 根据文档,我知道在 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
似乎采用配置参数,创建身份验证提供程序,并将user
、signOut
和signInWithGoogle
作为道具注入正在装饰的组件中,例如App
.
- 对withFireBaseAuth()的调用出现在App的定义之后,那么App.props.user怎么在App.render()中使用的时候不是undefined呢?
请记住,这些只是组件声明。App
组件在文件中声明,然后装饰,withFirebaseAuth
然后默认导出。
export default withFirebaseAuth({
providers,
firebaseAppAuth,
})(App);
App
React 默认导入并渲染其他地方(真正的装饰)。
import App from '../path/to/app';
ReactDOM.render(
<App />,
document.getElementById("root")
);
请注意,我们不需要传递任何道具,但是user
,signOut
和signInWithGoogle
将由withFirebaseAuth
.