【问题标题】:Converting this class to a functional component将此类转换为功能组件
【发布时间】:2020-12-06 16:35:45
【问题描述】:

我有以下代码,并希望尽可能使用挂钩将其转换为功能组件。我知道钩子似乎是 react 正在走向的方向。所以,我想确保我更多地使用功能组件而不是类来管理状态。

import React from 'react';
 
import AuthUserContext from './context';
import { withFirebase } from '../Firebase';
 
const withAuthentication = Component => {
  class WithAuthentication extends React.Component {
    constructor(props) {
      super(props);
 
      this.state = {
        authUser: null,
      };
    }
 
    componentDidMount() {
      this.listener = this.props.firebase.auth.onAuthStateChanged(
        authUser => {
          authUser
            ? this.setState({ authUser })
            : this.setState({ authUser: null });
        },
      );
    }
 
    componentWillUnmount() {
      this.listener();
    }
 
    render() {
      return (
        <AuthUserContext.Provider value={this.state.authUser}>
          <Component {...this.props} />
        </AuthUserContext.Provider>
      );
    }
  }
 
  return withFirebase(WithAuthentication);
};
 
export default withAuthentication;

这是我尝试过的,不知道如何绕过组件标签。

const withAuthentication = (Component) => {


const WithAuthentication = (props) => {
    
    const [authUser, setAuthUser] = useState(null);
 
    useEffect(() => {
      this.props.firebase.auth.onAuthStateChanged(
        authUser => {
          authUser
            ? setAuthUser(true)
            : setAuthUser(null);
        })
    }, [authUser]);
 
    return (
    <AuthUserContext.Provider value={authUser}>
        <Component {...this.props} />
    </AuthUserContext.Provider>
    );
  }
 
  return withFirebase(WithAuthentication);
};

【问题讨论】:

  • 如果您提供您尝试执行的代码 sn-ps 以显示您尝试解决此问题的努力,那么您更有可能获得帮助。现在我们不确定你是否尝试过这个。
  • @CertainPerformance 我用我尝试过的内容编辑我的帖子。组件部分是我对如何从课堂切换感到困惑的部分。

标签: reactjs react-hooks


【解决方案1】:

据我所知,有 4 点需要调整:

  • 在函数组件中,props 是一个参数 - 一个独立变量,而不是this 的属性。所以将this.props.firebase 更改为props.firebase。同样,&lt;Component {...this.props} /&gt; 应该是 &lt;Component {...props} /&gt;
  • 类组件执行this.setState({ authUser }),但功能组件执行setAuthUser(true)。如果是真的,你可能想改用setAuthUser(authUser)
  • 根据componentDidMountonAuthStateChanged 应该只在组件挂载时运行。所以useEffect中的依赖数组应该是空的,而不是每次authUser运行时都运行。 ([authUser] 应该是 []
  • componentWillUnmount 部分未转换为功能组件。从useEffect返回一个回调以在清理组件时运行它,看起来是onAuthStateChanged的返回值:
useEffect(() => {
  return this.props.firebase.auth.onAuthStateChanged(
    authUserResponse => {
      setAuthUser(authUserResponse || null);
    }
  );
}, []);

useEffect 的立即返回可能有点令人困惑——它相当于:

useEffect(() => {
  const listener = this.props.firebase.auth.onAuthStateChanged(
    authUserResponse => {
      setAuthUser(authUserResponse || null);
    }
  );
  return listener; // run listener function when component unmounts
}, []);

【讨论】:

  • 感谢您对使用 return 进行卸载的清晰说明。我从来没有从我看过的视频中了解到这一点。
【解决方案2】:

您需要使用props 参数并在setAuthUser(authUser) 使用authUser 本身。

对于componentWillUnmount 逻辑,您可以将其删除,因为它似乎没用。

const withAuthentication = (Component) => {

const WithAuthentication = (props) => {
    
    const [authUser, setAuthUser] = useState(null);
 
    useEffect(() => {
     props.firebase.auth.onAuthStateChanged(
        authUser => {
          authUser
            ? setAuthUser(authUser)
            : setAuthUser(null);
        })
    }, [authUser]);
  
    return (
    <AuthUserContext.Provider value={authUser}>
        <Component {...this.props} />
    </AuthUserContext.Provider>
    );
  }
 
  return withFirebase(WithAuthentication);
};

【讨论】:

    猜你喜欢
    • 2021-03-06
    • 1970-01-01
    • 2020-02-08
    • 2021-09-30
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 2022-01-08
    相关资源
    最近更新 更多