Reactjs React应用程序重定向到路由“/&引用;当我试图通过手动更改url进行导航时

Reactjs React应用程序重定向到路由“/&引用;当我试图通过手动更改url进行导航时,reactjs,react-router,Reactjs,React Router,我正在创建一个React应用程序,它将用户角色(有两个可能的角色0和1用于条件呈现)存储在“全局”React上下文中。角色在登录时分配。我还使用React路由器来处理路由,并编写了一个ProtectedRoute组件。我的问题是:当我通过导航栏导航时,一切都很好,但当我在url中输入例如/home时,我会被重定向到LoginPage(当角色未设置为0或1时,这是标准路由),我无法再访问其他路由。但是,用户没有注销(数据库中的会话没有被删除),应用程序似乎只是忘记了全局状态“角色”,它用于确定是否

我正在创建一个React应用程序,它将用户角色(有两个可能的角色0和1用于条件呈现)存储在“全局”React上下文中。角色在登录时分配。我还使用React路由器来处理路由,并编写了一个ProtectedRoute组件。我的问题是:当我通过导航栏导航时,一切都很好,但当我在url中输入例如/home时,我会被重定向到LoginPage(当角色未设置为0或1时,这是标准路由),我无法再访问其他路由。但是,用户没有注销(数据库中的会话没有被删除),应用程序似乎只是忘记了全局状态“角色”,它用于确定是否允许用户访问各个路由。恐怕我对DOM和路由器的知识太有限,无法解决这个问题

function App() {
  return (
    <AuthProvider>
      <Router>
          <NavigationBar />
          <AuthContext.Consumer>
            {context => (
              <React.Fragment>
                {!context.isAuthenticated() ? <Jumbotron/> : null}
              </React.Fragment>
            )}
          </AuthContext.Consumer>
          <Layout>
            <Switch>
              <Route exact path="/" component={() => <LandingPage />} />
              <ProtectedRoute path="/home" component={Home} />
              <ProtectedRoute path="/about" component={About}/>
              <ProtectedRoute path="/account" component={Account} />
              <ProtectedRoute path="/calender" component={Calender} />
              <ProtectedRoute path="/xyz" component={Xyz} />
              <ProtectedRoute path="/wasd" component={wasd} role={0} />
              <Route component={NoMatch} />
            </Switch>
          </Layout>
      </Router>
    </AuthProvider>
  );
}


export default App;
类AuthProvider扩展组件{
构造函数(){
超级();
此.state={
角色:2,//无=2
姓名:“,
电子邮件:“
};
}
render(){
返回(
{
if(this.state.role==1 | | this.state.role==0){
返回true;
}
返回false;
},
setRole:newRole=>
这是我的国家({
角色:新角色
}),
getRole:()=>{
返回此.state.role;
},
setName:newName=>
这是我的国家({
姓名:newName
}),
getName:()=>{
返回this.state.name;
},
setEmail:newEmail=>
这是我的国家({
电子邮件:newEmail
}),
getEmail:()=>{
返回此.state.email;
},
}}
>
{this.props.children}
);
}
}
导出默认AuthProvider;

如果您在浏览器中直接输入url,React将完全重新加载,您将丢失所有状态,无论是“全局”还是其他状态。最可能的情况是,您的路由器正在尝试验证您在获取身份验证数据之前查看组件的能力

您不包括如何从数据库获取身份验证会话,但即使您重新蚀刻身份验证会话,也会有一段时间您的应用程序已安装,但您还没有响应。这将使受保护的路由认为您未经授权,并重定向到回退路径


尝试在受保护的路由内部或路由器本身之前添加一个检查,该检查将阻止渲染,直到加载身份验证数据。虽然再次阅读您的问题时,您似乎根本没有重新访问登录用户。

这正是我在阅读问题时所想的。如果他们没有将身份验证/会话数据存储在持续存在的内容中,则每次刷新浏览器时,他们都将注销。如果您查看ProtectedRoute If isAuthenticated()为false,它将重定向到“/”。是的,重定向后它们无法到达其他受保护的路由这一事实更强烈地表明它们在页面加载时没有重新获取身份验证数据。我的第一个想法是,它们没有考虑身份验证请求和响应之间的时间,因为这是我犯过几次的错误……是的,没有提到Cookie或其他存储,因此如果不存储或重新获取,身份验证数据将在重新加载时擦除,然后重定向。获取一些工作代码的链接以了解其工作原理可能会有所帮助…?首先感谢你们两位的回答。这是一个大学项目的一部分,我和我的团队以前从未使用过React,也从未创建过任何类型的后端。到目前为止,一旦用户在route“/”的登录页上按下login键,就会设置上下文。我不知道,每次刷新都会重置它。因此,您的建议是将会话存储在本地存储中,并在每次调用Pr.Route时对照数据库中的会话进行检查?这不会导致大量的抓取吗?或者每次App.js再次挂载时,我可以使用useEffect仅获取数据。谢谢,当你的顶级组件像你说的那样挂载时,我会获取会话数据。没有必要在每次换车时都这样做。除非您有诸如超时之类的特殊逻辑(情况并非如此),否则您的会话数据只有在您登录或注销时才会更改。因此,这意味着您可以在开始时获得一次会话,并从此信任它,直到您再次执行这两个操作之一。
export const ProtectedRoute = ({ component: Component, ...rest }) => {
  const { isAuthenticated, getRole } = useContext(AuthContext);

  if (rest.role === 0) {
    return (
      <Route
        {...rest}
        render={props =>
          getRole() === 0 ? (
            <Component {...props} />
          ) : (
            <Redirect
              to={{
                pathname: "/404",
                state: {
                  from: props.location
                }
              }}
            />
          )
        }
      />
    );
  } else if (rest.role === 1) {
    return (
      <Route
        {...rest}
        render={props =>
          getRole() === 1 ? (
            <Component {...props} />
          ) : (
            <Redirect
              to={{
                pathname: "/404",
                state: {
                  from: props.location
                }
              }}
            />
          )
        }
      />
    );
  } else {
    return (
      <Route
        {...rest}
        render={props =>
          isAuthenticated() ? (
            <Component {...props} />
          ) : (
            <Redirect
              to={{
                pathname: "/",
                state: {
                  from: props.location
                }
              }}
            />
          )
        }
      />
    );
  }
};
import React from "react";

const AuthContext = React.createContext();

export default AuthContext;

class AuthProvider extends Component {
  constructor() {
    super();
    this.state = {
      role: 2, //none=2
      name: "",
      email: ""
    };
  }

  render() {
    return (
      <AuthContext.Provider
        value={{
          state: this.state,
          isAuthenticated: () => {
            if (this.state.role === 1 || this.state.role === 0) {
              return true;
            }
            return false;
          },
          setRole: newRole =>
            this.setState({
              role: newRole
            }),
          getRole: () => {
            return this.state.role;
          },
          setName: newName =>
            this.setState({
              name: newName
            }),
          getName: () => {
            return this.state.name;
            },
          setEmail: newEmail =>
            this.setState({
              email: newEmail
            }),
          getEmail: () => {
            return this.state.email;
            },
        }}
      >
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}

export default AuthProvider;