【问题标题】:React authentication with private routes and context使用私有路由和上下文响应身份验证
【发布时间】:2020-02-22 01:28:53
【问题描述】:

我正在尝试使用私有路由和上下文向 React+Typescript 应用程序添加简单的身份验证。我有一个简单的登录组件,它带有一个按钮,它只是将上下文中的布尔变量authenticated 设置为true。私有路由应该检查这个 var 并重定向到登录组件,如果它不是真的,否则显示指定的组件。问题是authenticated 似乎总是错误的,我总是被重定向到登录页面。

当我调试它时,我可以看到 AuthContextProvider 中的setAuthenticated 函数在单击登录按钮时被调用。但是,如果我随后单击任何指向私有路由的链接,authenticated 总是错误的。

这是我的 App.tsx:

function App() {

  return (
    <AuthContextProvider>
      <Router>
        <Link to="/">Home</Link>
        <Link to="/projects">Projects</Link>
        <div>
          <Route path="/login" component={Login} />
          <PrivateRoute path="/" exact component={Home} />
          <PrivateRoute path="/projects" component={Projects} />
        </div>
      </Router>
    </AuthContextProvider>
  );
} 

export default App;

PrivateRoute.tsx:

interface PrivateRouteProps extends RouteProps {
    // tslint:disable-next-line:no-any
    component: any;
}

const PrivateRoute = (props: PrivateRouteProps) => {
    const { component: Component, ...rest } = props;

    return (
      <AuthContextConsumer>
        {authContext => authContext && (

        <Route {...rest}
            render={ props => 
                authContext.authenticated === true  ? (
                    <Component {...props} />
                ) : (
                    <Redirect to="/login" />
                )
            }
        />

      )}
      </AuthContextConsumer>
    );
};

export default PrivateRoute;

AuthContext.tsx:

export interface AuthContextInterface {
  authenticated: boolean,
  setAuthenticated(newAuthState: boolean):void
}

const ctxt = React.createContext<AuthContextInterface>({
    authenticated: false,
    setAuthenticated: () => {}
  });

export class AuthContextProvider extends React.Component {
  setAuthenticated = (newAuthState:boolean) => {
    this.setState({ authenticated: newAuthState });
  };

  state = {
    authenticated: false,
    setAuthenticated: this.setAuthenticated,
  };

  render() {
    return (
      <ctxt.Provider value={this.state}>
        {this.props.children}
      </ctxt.Provider>
    );
  }
}  
export const AuthContextConsumer = ctxt.Consumer;

登录.tsx:

function Login() {

    return (
        <AuthContextConsumer>
        {({ authenticated, setAuthenticated }) => (
               <div>
                    <p>Login</p>
                    <form>
                        <input type="text" placeholder="Username"/>
                       <input type="password" placeholder="Password"/>
                        <button onClick={event => {
              setAuthenticated(true);
            }}>Login</button>
                    </form>
                </div>
        )}
        </AuthContextConsumer>
    );
}

export default Login;

我怀疑 AuthContextProvider 中的状态定义有问题。如果我在这里将authenticatedin 更改为 true,我会看到相反的行为,我永远不会看到登录页面。这应该是动态的吗?

【问题讨论】:

    标签: reactjs typescript react-router react-context


    【解决方案1】:

    或者,在 onClick 回调中,设置 event.preventDefault() 使其不提交表单。

    【讨论】:

      【解决方案2】:

      问题原来是每次按下登录按钮时应用都在重新加载,因此丢失了 AuthContext 中的状态。

      原因是在我的登录组件中,我在表单中有一个按钮,它会自动提交表单并重新加载页面。

      解决办法是要么去掉表单标签,要么在按钮中指定属性type="button"

      【讨论】:

        猜你喜欢
        • 2021-05-01
        • 2021-08-06
        • 1970-01-01
        • 2012-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-19
        • 1970-01-01
        相关资源
        最近更新 更多