Реагировать на аутентификацию с помощью частных маршрутов и контекста - PullRequest
0 голосов
/ 25 октября 2019

Я пытаюсь добавить простую аутентификацию в приложение React + Typescript, используя частные маршруты и контекст. У меня есть простой компонент входа в систему с кнопкой, которая просто устанавливает логическое значение var authenticated в контексте в значение true. Приватные маршруты должны проверить эту переменную и перенаправить на компонент входа в систему, если это не так, в противном случае показать указанный компонент. Проблема в authenticated, кажется, всегда ложной, и я всегда перенаправлен на страницу входа.

Когда я отлаживаю его, я вижу, что функция setAuthenticated в AuthContextProvider вызывается при нажатии кнопки входа в систему. Но если я затем нажму на любую из ссылок на частные маршруты, 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;

Login.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. Если я изменю authenticated здесь на true, я вижу противоположное поведение, я никогда не вижу страницу входа. Должно ли это быть чем-то динамичным?

1 Ответ

0 голосов
/ 28 октября 2019

Проблема оказалась в том, что приложение перезагружалось при каждом нажатии кнопки входа в систему, и поэтому теряло состояние в AuthContext.

Причина этого в том, что в моем компоненте входа в систему у меня былкнопка внутри формы, которая автоматически отправляет форму и перезагружает страницу.

Решение состоит в том, чтобы либо удалить теги формы, либо в кнопке указать атрибут type="button".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...