인증된 경로를 구현하려고 했지만 React 라우터 4에서 이 기능이 작동하지 않는 것을 발견했습니다:
<Route exact path="/" component={Index} />
<Route path="/auth" component={UnauthenticatedWrapper}>
<Route path="/auth/login" component={LoginBotBot} />
</Route>
<Route path="/domains" component={AuthenticatedWrapper}>
<Route exact path="/domains" component={DomainsIndex} />
</Route>
오류입니다:
Warning: 동일한 경로에
<Route component<
와<Route children<
를 사용하면 안 됩니다;<Route children<
는 무시됩니다.
이 경우 이를 구현하는 올바른 방법은 무엇인가요?
그것은 반응 라우터
(v4) 문서에 나타나며 다음과 같은 것을 제안합니다.
<Router>
<div>
<AuthButton/>
<ul>
<li><Link to="/public">Public Page</Link></li>
<li><Link to="/protected">Protected Page</Link></li>
</ul>
<Route path="/public" component={Public}/>
<Route path="/login" component={Login}/>
<PrivateRoute path="/protected" component={Protected}/>
</div>
</Router>
하지만 여러 경로를 함께 그룹화하면서 이를 달성할 수 있을까요?
업데이트
몇 가지 조사 끝에 이 방법을 생각해냈습니다:
import React, {PropTypes} from "react"
import {Route} from "react-router-dom"
export default class AuthenticatedRoute extends React.Component {
render() {
if (!this.props.isLoggedIn) {
this.props.redirectToLogin()
return null
}
return <Route {...this.props} />
}
}
AuthenticatedRoute.propTypes = {
isLoggedIn: PropTypes.bool.isRequired,
component: PropTypes.element,
redirectToLogin: PropTypes.func.isRequired
}
렌더()에서 액션을 디스패치하는 것이 올바른가요? 컴포넌트디드마운트
나 다른 훅을 사용하는 것도 옳지 않은 것 같나요?
'리디렉션' 컴포넌트를 사용하고 싶을 것입니다. 이 문제에 대한 몇 가지 다른 접근 방식이 있습니다. 제가 좋아하는 방법은 '인증된' 소품을 가져온 다음 해당 소품을 기반으로 렌더링하는 PrivateRoute 컴포넌트를 사용하는 것입니다.
function PrivateRoute ({component: Component, authed, ...rest}) {
return (
<Route
{...rest}
render={(props) => authed === true
? <Component {...props} />
: <Redirect to={{pathname: '/login', state: {from: props.location}}} />}
/>
)
}
이제 '경로'는 다음과 같이 보일 수 있습니다.
<Route path='/' exact component={Home} />
<Route path='/login' component={Login} />
<Route path='/register' component={Register} />
<PrivateRoute authed={this.state.authed} path='/dashboard' component={Dashboard} />
여전히 헷갈리신다면, 제가 작성한 이 글이 도움이 될 수 있습니다 - [ React 라우터 v4로 보호된 경로와 인증
타일러 맥기니스에게 솔루션을 요청합니다. 저는 타일러 맥기니스의 아이디어에서 아이디어를 얻습니다.
const DecisionRoute = ({ trueComponent, falseComponent, decisionFunc, ...rest }) => {
return (
<Route
{...rest}
render={
decisionFunc()
? trueComponent
: falseComponent
}
/>
)
}
다음과 같이 구현할 수 있습니다.
<DecisionRoute path="/signin" exact={true}
trueComponent={redirectStart}
falseComponent={SignInPage}
decisionFunc={isAuth}
/>
decisionFunc는 참 또는 거짓을 반환하는 함수일 뿐입니다.
const redirectStart = props => <Redirect to="/orders" />
만 추가하면 내 문제를 해결하는 솔루션.
내가 사용하 jwt 토큰에 대한 인증는 경우,그래서 그 사용자가는 토큰한 다음 나이로 리디렉션 홈 페이지 또는 다른 나이로 리디렉션 로그인 페이지에서 기본값(이 경로'/'). 그래서 한번 사용자에 기록되었습니다 액세스하려고 로그인 페이지의 url 을(내 사례'/') . 나이로 리디렉션 홈 기본적으로('/가정').
와 나의 구성 요소를 할 수 있는 임시명 requireAuth 확인하려면 사용자는 토큰의 유효합니다.그렇지 않으면 다음 전화는 아웃 행동을 제거하는 localhistory 토큰을 발급합니다.
import React, { Component, Fragment } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter, Route, Switch, Redirect } from 'react-router-dom';
//and also import appropriate components
//middleware
class checkStatus extends React.Component {
render() {
if(localStorage.getItem('token')){
return (
<Fragment>
<App>
<Route path="/home" exact component={Overview} />
<Route path="/home/add" exact component={Add} />
<Route path="/signout" component={Signout} />
<Route path="/details" component={details} />
<Route exact path="/" render={() => <Redirect to="/home" />} />
</App>
</Fragment>
)
}else{
return (
<Fragment>
<Route path="/" exact component={Signin} />
<Redirect to="/" />
</Fragment>
)
}
} }
ReactDOM.render( <Provider store={store}>
<BrowserRouter>
<Switch >
<Route path="/" exact component={checkStatus} />
<Route path="/:someParam" component={checkStatus}/>
</Switch >
</BrowserRouter> </Provider>, document.querySelector('#root')
);
설치는 반응 라우터 dom
을 만든 다음 두 가지 요소 중 하나에 대한 유효한 사용자와는 다른 대한 잘못된 사용자.
이 app.js
import React from 'react';
import {
BrowserRouter as Router,
Route,
Link,
Switch,
Redirect
} from 'react-router-dom';
import ValidUser from "./pages/validUser/validUser";
import InValidUser from "./pages/invalidUser/invalidUser";
const loggedin = false;
class App extends React.Component {
render() {
return (
<Router>
<div>
<Route exact path="/" render={() =>(
loggedin ? ( <Route component={ValidUser} />)
: (<Route component={InValidUser} />)
)} />
</div>
</Router>
)
}
}
export default App;
기반의 대답에@맥 지니스 타일러. 나는 다른 방법을 사용하여ES6 구문과중첩된 노선으로 싸여 구성 요소:
import React, { cloneElement, Children } from 'react'
import { Route, Redirect } from 'react-router-dom'
const PrivateRoute = ({ children, authed, ...rest }) =>
<Route
{...rest}
render={(props) => authed ?
<div>
{Children.map(children, child => cloneElement(child, { ...child.props }))}
</div>
:
<Redirect to={{ pathname: '/', state: { from: props.location } }} />}
/>
export default PrivateRoute
고 그것을 사용:
<BrowserRouter>
<div>
<PrivateRoute path='/home' authed={auth}>
<Navigation>
<Route component={Home} path="/home" />
</Navigation>
</PrivateRoute>
<Route exact path='/' component={PublicHomePage} />
</div>
</BrowserRouter>
나는 그것을 알's 되는 동안 그러나 나는've 에서 작업하는npm 패키지에 대한 민간 및 공공 노선이 있습니다.
여기's 하는 방법을 확인인 경로:
<PrivateRoute exact path="/private" authed={true} redirectTo="/login" component={Title} text="This is a private route"/>
할 수 있도 대중 경로만 사용자가 액세스할 수 있 unauthed
<PublicRoute exact path="/public" authed={false} redirectTo="/admin" component={Title} text="This route is for unauthed users"/>
I hope it helps!
내 이전에 응답하지 않은 확장성을 보장할 수 있습니다. 여기에 내가 무엇을 생각하는 좋은 방법-
귀하의 노선-
<Switch>
<Route
exact path="/"
component={matchStateToProps(InitialAppState, {
routeOpen: true // no auth is needed to access this route
})} />
<Route
exact path="/profile"
component={matchStateToProps(Profile, {
routeOpen: false // can set it false or just omit this key
})} />
<Route
exact path="/login"
component={matchStateToProps(Login, {
routeOpen: true
})} />
<Route
exact path="/forgot-password"
component={matchStateToProps(ForgotPassword, {
routeOpen: true
})} />
<Route
exact path="/dashboard"
component={matchStateToProps(DashBoard)} />
</Switch>
아이디어가 사용하는 래퍼에서는구성 요소
소품을 반환하는 원래의 구성요소가 없는 경우 인증 필요한 또는 이미 인증을 그렇지 않으면 반환하는 기본 구성 요소 예로 로그인합니다.
const matchStateToProps = function(Component, defaultProps) {
return (props) => {
let authRequired = true;
if (defaultProps && defaultProps.routeOpen) {
authRequired = false;
}
if (authRequired) {
// check if loginState key exists in localStorage (Your auth logic goes here)
if (window.localStorage.getItem(STORAGE_KEYS.LOGIN_STATE)) {
return <Component { ...defaultProps } />; // authenticated, good to go
} else {
return <InitialAppState { ...defaultProps } />; // not authenticated
}
}
return <Component { ...defaultProps } />; // no auth is required
};
};
내가 사용하여 구현-
<Route path='/dashboard' render={() => (
this.state.user.isLoggedIn ?
(<Dashboard authenticate={this.authenticate} user={this.state.user} />) :
(<Redirect to="/login" />)
)} />
증 소품이 전달되는 구성 요소 예:가입을 사용하는 사용자의 상태를 변경할 수 있습니다. 완전 AppRoutes-
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { Redirect } from 'react-router';
import Home from '../pages/home';
import Login from '../pages/login';
import Signup from '../pages/signup';
import Dashboard from '../pages/dashboard';
import { config } from '../utils/Config';
export default class AppRoutes extends React.Component {
constructor(props) {
super(props);
// initially assuming that user is logged out
let user = {
isLoggedIn: false
}
// if user is logged in, his details can be found from local storage
try {
let userJsonString = localStorage.getItem(config.localStorageKey);
if (userJsonString) {
user = JSON.parse(userJsonString);
}
} catch (exception) {
}
// updating the state
this.state = {
user: user
};
this.authenticate = this.authenticate.bind(this);
}
// this function is called on login/logout
authenticate(user) {
this.setState({
user: user
});
// updating user's details
localStorage.setItem(config.localStorageKey, JSON.stringify(user));
}
render() {
return (
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/login' render={() => <Login authenticate={this.authenticate} />} />
<Route exact path='/signup' render={() => <Signup authenticate={this.authenticate} />} />
<Route path='/dashboard' render={() => (
this.state.user.isLoggedIn ?
(<Dashboard authenticate={this.authenticate} user={this.state.user} />) :
(<Redirect to="/login" />)
)} />
</Switch>
);
}
}
체크의 완전한 프로젝트 여기:https://github.com/varunon9/hello-react
컴포넌트를 직접 생성한 다음 렌더링 메서드로 디스패치하는 것이 망설여지시나요? Route컴포넌트의
render메서드를 사용하면 두 가지를 모두 피할 수 있습니다. 정말 원하지 않는 한
<AuthenticatedRoute컴포넌트를 만들 필요가 없습니다. 아래와 같이 간단하게 만들 수 있습니다. 루트 컴포넌트의 프로퍼티를 하위 컴포넌트(이 경우 ``내 컴포넌트``)로 계속 보내도록
{...routeProps}` 스프레드에 유의하세요.
<Route path='/someprivatepath' render={routeProps => {
if (!this.props.isLoggedIn) {
this.props.redirectToLogin()
return null
}
return <MyComponent {...routeProps} anotherProp={somevalue} />
} />
React 라우터 V4 렌더링 문서]1를 참조하세요.
전용 컴포넌트를 만들고 싶었다면, 올바른 방향으로 가고 있는 것 같습니다. 리액트 라우터 V4는 순전히 선언적 라우팅이기 때문에(설명에 바로 그렇게 나와 있습니다) 리디렉션 코드를 일반적인 컴포넌트 수명 주기 밖에 두어도 문제가 없을 것 같습니다. 리액트 라우터 자체의 코드]3를 보면, 서버 측 렌더링인지 아닌지에 따라 componentWillMount
또는 componentDidMount
에서 리디렉션을 수행합니다. 아래 코드는 매우 간단하며 리디렉션 로직을 어디에 배치할지 결정하는 데 도움이 될 수 있습니다.
import React, { PropTypes } from 'react'
/**
* The public API for updating the location programatically
* with a component.
*/
class Redirect extends React.Component {
static propTypes = {
push: PropTypes.bool,
from: PropTypes.string,
to: PropTypes.oneOfType([
PropTypes.string,
PropTypes.object
])
}
static defaultProps = {
push: false
}
static contextTypes = {
router: PropTypes.shape({
history: PropTypes.shape({
push: PropTypes.func.isRequired,
replace: PropTypes.func.isRequired
}).isRequired,
staticContext: PropTypes.object
}).isRequired
}
isStatic() {
return this.context.router && this.context.router.staticContext
}
componentWillMount() {
if (this.isStatic())
this.perform()
}
componentDidMount() {
if (!this.isStatic())
this.perform()
}
perform() {
const { history } = this.context.router
const { push, to } = this.props
if (push) {
history.push(to)
} else {
history.replace(to)
}
}
render() {
return null
}
}
export default Redirect
Heres 방법과 반응과 호환되지 않. Hope it helps!
import * as React from 'react';
import { Route, RouteComponentProps, RouteProps, Redirect } from 'react-router';
const PrivateRoute: React.SFC<RouteProps> = ({ component: Component, ...rest }) => {
if (!Component) {
return null;
}
const isLoggedIn = true; // Add your provider here
return (
<Route
{...rest}
render={(props: RouteComponentProps<{}>) => isLoggedIn ? (<Component {...props} />) : (<Redirect to={{ pathname: '/', state: { from: props.location } }} />)}
/>
);
};
export default PrivateRoute;
<PrivateRoute component={SignIn} path="/signin" />
const Root = ({ session }) => {
const isLoggedIn = session && session.getCurrentUser
return (
<Router>
{!isLoggedIn ? (
<Switch>
<Route path="/signin" component={<Signin />} />
<Redirect to="/signin" />
</Switch>
) : (
<Switch>
<Route path="/" exact component={Home} />
<Route path="/about" component={About} />
<Route path="/something-else" component={SomethingElse} />
<Redirect to="/" />
</Switch>
)}
</Router>
)
}
여기에 간단한 청소 보팅
const ProtectedRoute
= ({ isAllowed, ...props }) =>
isAllowed
? <Route {...props}/>
: <Redirect to="/authentificate"/>;
const _App = ({ lastTab, isTokenVerified })=>
<Switch>
<Route exact path="/authentificate" component={Login}/>
<ProtectedRoute
isAllowed={isTokenVerified}
exact
path="/secrets"
component={Secrets}/>
<ProtectedRoute
isAllowed={isTokenVerified}
exact
path="/polices"
component={Polices}/>
<ProtectedRoute
isAllowed={isTokenVerified}
exact
path="/grants" component={Grants}/>
<Redirect from="/" to={lastTab}/>
</Switch>
isTokenVerified
는 방법을 확인하기 위해 호출 승인 토큰을 기본적으로 반환합니다.
또한 일부를 찾고 대답합니다. 여기에는 모든 대답은 아주 좋은,하지만 아무도 그들의 답변을 제공할 수 있는 방법을 사용하는 경우에는 사용자가 응용 프로그램 개봉 후습니다. (나는 말을 사용하여 쿠키 함께).
을 만들 필요가 없더라도 다른 privateRoute 구성 요소입니다. 아래에 나의 코드
import React, { Component } from 'react';
import { Route, Switch, BrowserRouter, Redirect } from 'react-router-dom';
import { Provider } from 'react-redux';
import store from './stores';
import requireAuth from './components/authentication/authComponent'
import SearchComponent from './components/search/searchComponent'
import LoginComponent from './components/login/loginComponent'
import ExampleContainer from './containers/ExampleContainer'
class App extends Component {
state = {
auth: true
}
componentDidMount() {
if ( ! Cookies.get('auth')) {
this.setState({auth:false });
}
}
render() {
return (
<Provider store={store}>
<BrowserRouter>
<Switch>
<Route exact path="/searchComponent" component={requireAuth(SearchComponent)} />
<Route exact path="/login" component={LoginComponent} />
<Route exact path="/" component={requireAuth(ExampleContainer)} />
{!this.state.auth && <Redirect push to="/login"/> }
</Switch>
</BrowserRouter>
</Provider>);
}
}
}
export default App;
그리고 여기에 authComponent
import React from 'react';
import { withRouter } from 'react-router';
import * as Cookie from "js-cookie";
export default function requireAuth(Component) {
class AuthenticatedComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
auth: Cookie.get('auth')
}
}
componentDidMount() {
this.checkAuth();
}
checkAuth() {
const location = this.props.location;
const redirect = location.pathname + location.search;
if ( ! Cookie.get('auth')) {
this.props.history.push(`/login?redirect=${redirect}`);
}
}
render() {
return Cookie.get('auth')
? <Component { ...this.props } />
: null;
}
}
return withRouter(AuthenticatedComponent)
}
아래 나 블로그를 얻을 수 있는 더 깊이 설명이 있을 뿐입니다.