当前位置: 代码迷 >> JavaScript >> 如何更新高阶组件
  详细解决方案

如何更新高阶组件

热度:111   发布时间:2023-06-12 14:07:58.0

我在ReactJS中创建了路由数组

const routes = [
  { id: 0, path: '/', view: Home, parent: 0 },
  { id: 1, path: '/a', view: Home2, parent: 0 },
  { id: 2, path: '/b', view: Home3, parent: 1 }
]

创建了具有认证的HOC withAuth,当未登录用户时应返回到父路由。 当我要进行路由(未登录)时,可以正常使用withAuth将其返回到父路由,但是当我在路由上并且注销页面未刷新时,我将保留在已登录用户的路由上。

import React, { Component } from "react";
import AuthHelper from "./AuthHelper";

export default function withAuth(AuthComponent) {
  const Auth = new AuthHelper();

  class AuthWrapped extends Component {
    constructor(props) {
      super(props);

      this.state = {
        confirm: null,
        loaded: false
      };
    }

    checkLogged = () => {
      if (!Auth.loggedIn()) {

        const parent = this.props.parent;
        const obj = this.props.routes
        .filter(v => v.id === parent);
        this.props.history.replace(obj[0].path);

      } else {
        try {
          const confirm = Auth.getConfirm();
          this.setState({
            confirm: confirm,
            loaded: true
          });
        } catch (err) {
          Auth.logout();
          this.props.history.replace("/");
        }
      }
    }

    componentDidMount() {
      this.checkLogged();
    }

    render() {
      if (this.state.loaded) {
        if (this.state.confirm) {
          return (
            <AuthComponent
              history={this.props.history}
              confirm={this.state.confirm}
            />
          );
        } else {
          return null;
        }
      } else {
        return null;
      }
    }
  };

  return AuthWrapped;
}

我相信您使用错误的身份验证系统
在React中,一切都应该以分层的方式存在。

在您的情况下,您的Auth状态将发生变化,并且当登录状态发生变化时,所有内容都应重新呈现。 正确的方法是使用Context API处理登录状态,因此当状态更改时,整个屏幕将重新呈现


这是您的问题的解决方案:

AuthContext.js

const AuthContext = React.createContext();

export class AuthProvider extends React.Component {
  state = {
    isLoggedIn: false,
  };

  login = (username, password) => {
    someLoginRequestToServer(username, password).then(response => {
      this.setState({
        isLoggedIn: response.isLoggedIn,
      });
    });
  };

  logout = () => {
    someLogoutRequestToServer().then(() => {
      this.setState({ isLoggedIn: false });
    });
  };

  render() {
    return (
      <AuthContext.Provider
        value={{
          loggedIn: this.state.isLoggedIn,
          login: this.login,
          logout: this.logout,
        }}>
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}

export const AuthConsumer = AuthContext.Consumer;

SomeCustomAuthComponent

class CustomAuthComponent extends React.Component {
  render() {
    return (
      <AuthConsumer>
        {({ loggedIn, login, logout }) => (
          <div>
            <p>You Are {loggedIn ? 'Logged in' : 'Logged out'}</p>
            <button onClick={loggedIn ? () => logout() : () => login('abcd', '12345')} />
          </div>
        )}
      </AuthConsumer>
    );
  }
}

或者,您可以使用redux进行状态管理,并使用react-redux,因为它使用了底层的react Context API。

希望这对您有帮助! :)

问题出在这里

componentDidMount() {
 this.checkLogged();
}

您正在检查是否仅在安装组件时(实例化之后)才记录用户。 您应该在每次页面更新时都对其进行检查,例如,必须使用componentDidUpdate钩子来确定一种处理此机制的方法。

export default function withAuth(AuthComponent) {
  const Auth = new AuthHelper();

  class AuthWrapped extends Component {
    constructor(props) {
      super(props);

      this.state = {
        confirm: null,
        loaded: false
      };
    }

    checkIsNotLogged = () => {
      const parent = this.props.parent;
      const obj = this.props.routes
        .filter(v => v.id === parent);
      this.props.history.replace(obj[0].path);
    }

    checkLogged = () => {
      if (!Auth.loggedIn()) {
        this.checkIsNotLogged();

      } else {
        try {
          const confirm = Auth.getConfirm();
          this.setState({
            confirm: confirm,
            loaded: true
          });
        } catch (err) {
          Auth.logout();
          this.props.history.replace("/");
        }
      }
    }

    componentDidMount() {
      this.checkLogged();
    }

    componentDidUpdate() {
      // do not call here the checkLogged method otherwise you could trigger an infinite loop
      this.checkIsNotLogged();
    }

    render() {
      if (this.state.loaded) {
        if (this.state.confirm) {
          return (
            <AuthComponent
              history={this.props.history}
              confirm={this.state.confirm}
            />
          );
        } else {
          return null;
        }
      } else {
        return null;
      }
    }
  };

  return AuthWrapped;
}
  相关解决方案