如何根据状态变化重新渲染组件

时间:2020-02-15 23:32:40

标签: javascript reactjs

在尝试访问任何需要身份验证的组件时,如果未记录,我将尝试重定向到登录页面。 在尝试使用Firebase身份验证时,身份验证对象并不总是初始化的,并且延迟很小,因此根据文档,我必须使用onAuthStateChanged()事件侦听器,该侦听器都可以与显示已登录用户的导航栏一起正常使用。 但是,当尝试对已登录用户进行重定向时,由于始终未显示初始设置authuser的状态并且似乎已经进行了路由,因此始终显示初始登录对话框,因此无法正常工作。我在这里看到了类似的问题(Firebase, Avoid Logged-in user to visit login page),但当我直接进入url时,我并不能真正理解如何使用其中一个注释中的建议cookie /查询字符串,因为会话之间的初始延迟仍然很小值已设置并呈现,因此看不到第一次使用该方式将如何工作。对React来说是全新的,所以希望这个问题有意义。

PrivateRoute.js:

awk-mode

1 个答案:

答案 0 :(得分:0)

我从未使用过Firebase,但我正在做类似的事情。

比方说,我有自定义的钩子,可以在其中获取令牌,登录和注销功能。

这是我的app.js样子。如果用户有权访问,我将获得令牌。如果授予访问权限,它将获得令牌,然后设置路由并重定向到管理控制台。

function App() {
  const { token, login, logout } = useAuth();
  let routes;

  if (token) {
    routes = (
      <Switch>
        <Redirect to="/dashboard" />
      </Switch>
    );
  } else {
    routes = (
      <Switch>
        <Redirect to="/login" />
        <Route path="/" exact component={Layout} />
      </Switch>
    )
  }

  return (
    <AuthContext.Provider
      value={{
        isLoggedIn: !!token,
        token: token,
        login: login,
        logout: logout,
      }}
    >
      <Navigation />
      <Router>
        <main>
          {routes}
        </main>
      </Router>
    </AuthContext.Provider>
  );
}

这就是我的导航样子

const Navigation = () => {
  const auth = useContext(AuthContext);

  return (
    <>
      { auth.isLoggedIn && (<AdminNavigation />) }
      { !auth.isLoggedIn && (<UserNavigation />) }
    </>
  );
};

这是我的登录组件的外观

const SignIn = () => {
  const auth = useContext(AuthContext);
  const classes = useStyles();

  const {
    // eslint-disable-next-line no-unused-vars
    isLoading, error, sendRequest, clearError,
  } = useHttpClient();

  const [password, setPassword] = useState('');
  const [email, setEmail] = useState('');
  const [isLoggedIn, setIsLoggedIn] = useState(true);

  const updateInput = (event) => {
    if (event.target.id.toLowerCase() === 'email') {
      setEmail(event.target.value);
    } else {
      setPassword(event.target.value);
    }
  };

  const handleSwitchMode = () => {
    setIsLoggedIn((prevMode) => !prevMode);
  };

  const authSubmitHandler = async (event) => {
    event.preventDefault();

    setIsLoggedIn(true);
    // auth.login();

    if (isLoggedIn) {
      try {
        const responseData = await sendRequest(
          `${API_URL}/admin/login`,
          'POST',
          JSON.stringify({
            email,
            password,
          }),
          {
            'Content-Type': 'application/json',
          },
        );
        setIsLoggedIn(false);
        auth.login(responseData.token);
      } catch (err) {
        setIsLoggedIn(false);
      }
    } else {
      try {
        const responseData = await sendRequest(
          `${API_URL}/admin/signup`,
          'POST',
          JSON.stringify({
          // name,
            email,
            password,
          }),
          {
            'Content-Type': 'application/json',
          },
        );
        auth.login(responseData.token);
      } catch (err) {
        clearError();
      }
    }
  };


return (
    <Container component="main" maxWidth="xs">
      <div className={classes.paper}>
        <Typography component="h1" variant="h5">
          {isLoggedIn ? 'Login' : 'Sign up'}
        </Typography>
        <form className={classes.form} noValidate>
          {!isLoggedIn && (
            <TextField
              variant="outlined"
              margin="normal"
              required
              fullWidth
              id="name"
              label="Your name"
              autoFocus
              onChange={updateInput}
            />
          )}

          <TextField
            variant="outlined"
            margin="normal"
            required
            fullWidth
            id="email"
            label="Email Address"
            name="email"
            autoComplete="email"
            autoFocus
            value={email}
            onChange={updateInput}
          />
          <TextField
            variant="outlined"
            margin="normal"
            required
            fullWidth
            name="password"
            label="Password"
            type="password"
            id="password"
            value={password}
            autoComplete="current-password"
            onChange={updateInput}
          />
          <FormControlLabel
            control={<Checkbox value="remember" color="primary" />}
            label="Remember me"
          />
          <Button
            type="submit"
            fullWidth
            variant="contained"
            color="primary"
            className={classes.submit}
            onClick={authSubmitHandler}
          >
            {isLoggedIn ? 'Login' : 'Sign up'}
          </Button>
          <Grid container>
            <Grid item xs>
              <Link href="/" variant="body2">
                Forgot password?
              </Link>
            </Grid>
            <Grid item>
              <Button
                onClick={handleSwitchMode}
              >
                Dont have an account? Sign Up
              </Button>
            </Grid>
          </Grid>
        </form>
      </div>
    </Container>
  );

希望这会有所帮助。