Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/477.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 认证后未呈现的注销组件变为true这与react router docs中的代码类似_Javascript_Reactjs_React Router_React Router Dom_React Router V4 - Fatal编程技术网

Javascript 认证后未呈现的注销组件变为true这与react router docs中的代码类似

Javascript 认证后未呈现的注销组件变为true这与react router docs中的代码类似,javascript,reactjs,react-router,react-router-dom,react-router-v4,Javascript,Reactjs,React Router,React Router Dom,React Router V4,我刚刚尝试在浏览器上构建react router docs ex,但AuthButton组件中存在问题,当isAuthenticated变为true时,它没有显示signOut按钮 import React from 'react'; import { BrowserRouter as Router, Switch, Route, Link, Redirect, useHistory, useLocation, } from 'react-

我刚刚尝试在浏览器上构建react router docs ex,但AuthButton组件中存在问题,当isAuthenticated变为true时,它没有显示signOut按钮

import React from 'react';
import {
    BrowserRouter as Router,
    Switch,
    Route,
    Link,
    Redirect,
    useHistory,
    useLocation,
} from 'react-router-dom';



export default function AuthExample() {
    return (
        <Router>
            <div>
                <AuthButton />

                <ul>
                    <li>
                        <Link to='/public'>Public Page</Link>
                    </li>
                    <li>
                        <Link to='/protected'>Protected Page</Link>
                    </li>
                </ul>

                <Switch>
                    <Route path='/public'>
                        <PublicPage />
                    </Route>
                    <Route path='/login'>
                        <LoginPage />
                    </Route>
                    <PrivateRoute path='/protected'>
                        <ProtectedPage />
                    </PrivateRoute>
                </Switch>
            </div>
        </Router>
    );
}

const fakeAuth = {
    isAuthenticated: false,
    authenticate(cb) {
        fakeAuth.isAuthenticated = true;
        setTimeout(cb, 100); // fake async
    },
    signout(cb) {
        fakeAuth.isAuthenticated = false;
        setTimeout(cb, 100);
    },
};
function AuthButton() {
    let history = useHistory();

    return fakeAuth.isAuthenticated ? (
        <p>
            Welcome!{' '}
            <button
                onClick={() => {
                    fakeAuth.signout(() => history.push('/'));
                }}>
                Sign out
            </button>
        </p>
    ) : (
        <p>You are not logged in.</p>
    );
}


function PrivateRoute({ children, ...rest }) {
    return (
        <Route
            {...rest}
            render={({ location }) =>
                fakeAuth.isAuthenticated ? (
                    children
                ) : (
                    <Redirect
                        to={{
                            pathname: '/login',
                            state: { from: location },
                        }}
                    />
                )
            }
        />
    );
}

function PublicPage() {
    return <h3>Public</h3>;
}

function ProtectedPage() {
    return <h3>Protected</h3>;
}

function LoginPage() {
    let history = useHistory();
    let location = useLocation();

    let { from } = location.state || { from: { pathname: '/' } };
    let login = () => {
        fakeAuth.authenticate(() => {
            history.replace(from);
        });
    };

    return (
        <div>
            <p>You must log in to view the page at {from.pathname}</p>
            <button onClick={login}>Log in</button>
        </div>
    );
}

我认为问题出在渲染过程中。 在我看来,如果你把子函数放到导出函数中,这个问题可能会解决

如果问题无法解决,请尝试使用类基组件来处理此渲染过程


祝您成功

它不更新的原因是因为它不知道如何更新。您更改了路线,但AuthButton不知道根据需要传递道具的路线重新渲染,以便它知道何时更新。我重构了您的代码以使用。通过使用钩子,您可以通过useState在AuthExample的本地状态中存储isAuthenticated

在AuthExample中,将isAuthenticated的状态值作为道具传递给AuthButton。如果道具更改,AuthButton将检测到它,这将触发AuthButton的重新渲染,并反映您正在寻找的正确组件结构。见下文

import React, { useState } from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  Redirect,
  useHistory,
  useLocation
} from "react-router-dom";

export default function AuthExample() {
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  const fakeAuth = {
    isAuthenticated: isAuthenticated,
    authenticate(cb) {
      fakeAuth.isAuthenticated = true;
      setIsAuthenticated(true);
      setTimeout(cb, 100); // fake async
    },
    signout(cb) {
      setIsAuthenticated(false);
      fakeAuth.isAuthenticated = false;
      setTimeout(cb, 100);
    }
  };

  return (
    <Router>
      <div>
        <AuthButton fakeAuth={fakeAuth} isAuthenticated={isAuthenticated} />

        <ul>
          <li>
            <Link to="/public">Public Page</Link>
          </li>
          <li>
            <Link to="/protected">Protected Page</Link>
          </li>
        </ul>

        <Switch>
          <Route path="/public">
            <PublicPage />
          </Route>
          <Route path="/login">
            <LoginPage fakeAuth={fakeAuth} />
          </Route>
          <PrivateRoute path="/protected" fakeAuth={fakeAuth}>
            <ProtectedPage />
          </PrivateRoute>
        </Switch>
      </div>
    </Router>
  );
}

function AuthButton(props) {
  const { fakeAuth, isAuthenticated } = props;
  let history = useHistory();

  return isAuthenticated ? (
    <p>
      Welcome!{" "}
      <button
        onClick={() => {
          fakeAuth.signout(() => history.push("/"));
        }}
      >
        Sign out
      </button>
    </p>
  ) : (
    <p>You are not logged in.</p>
  );
}

function PrivateRoute({ children, ...rest }) {
  const { fakeAuth } = rest;

  return (
    <Route
      {...rest}
      render={({ location }) =>
        fakeAuth.isAuthenticated ? (
          children
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: location }
            }}
          />
        )
      }
    />
  );
}

function PublicPage() {
  return <h3>Public</h3>;
}

function ProtectedPage() {
  return <h3>Protected</h3>;
}

function LoginPage(props) {
  const { fakeAuth } = props;

  let history = useHistory();
  let location = useLocation();

  let { from } = location.state || { from: { pathname: "/" } };
  let login = () => {
    fakeAuth.authenticate(() => {
      history.replace(from);
    });
  };

  return (
    <div>
      <p>You must log in to view the page at {from.pathname}</p>
      <button onClick={login}>Log in</button>
    </div>
  );
}


您还可以看到一个工作示例。有几种方法可以做到这一点,但是钩子使操作状态值来更新功能组件变得很容易,而不必使它们成为类组件。这种方法还可以保持大部分代码的完整性,因为只需添加一些检查,以确定何时更新了isAuthenticated。

这应该是一个注释,而不是回答。这是您的意见,tnx@artmSkoltz的意思是,内容不足以作为答案,因为它不包含真正的解决方案、代码或引用,相反,它给出的是简短的建议和模糊的解决方案。将来一定要包含代码和/或引用,这样解决方案就更具体,而不是抽象的想法。谢谢,我下次会记得它。您的AuthButton似乎未连接到身份验证,因此在连接到身份验证之前它不会更改。尝试使用上下文允许其接收isAuthenticated