programing

리액트 라우터 프라이빗루트/리다이렉트가 기능하지 않음

yoursource 2023. 3. 18. 14:26
반응형

리액트 라우터 프라이빗루트/리다이렉트가 기능하지 않음

개인 루트가 Redx와 잘 작동하도록 리액트라우터의 예를 약간 조정했지만 다른 '페이지'로의 링크 또는 리다이렉트 시 컴포넌트는 렌더링되지 않습니다.예를 다음에 나타냅니다.

https://reacttraining.com/react-router/web/example/auth-workflow

PrivateRoute 컴포넌트는 다음과 같습니다.

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={props => (
    fakeAuth.isAuthenticated ? (
      <Component {...props}/>
    ) : (
      <Redirect to={{
        pathname: '/login',
        state: { from: props.location }
      }}/>
    )
  )}/>
)

단, Redux 어플리케이션에 통합했기 때문에 Redux 스토어와 Propos: 루트에 접속할 수 있도록 Private Route를 조금 조정해야 했습니다.

const PrivateRouteComponent = (props) => (
    <Route {...props.routeProps} render={() => (
    props.logged_in ? (
        <div>{props.children}</div>
        ) : (
        <Redirect to={{
            pathname: '/login',
            state: { from: props.location }
        }} /> )
    )} />
);

const mapStateToProps = (state, ownProps) => {
    return {
        logged_in: state.auth.logged_in,
        location: ownProps.path,
        routeProps: {
            exact: ownProps.exact,
            path: ownProps.path
        }
    };
};

const PrivateRoute = connect(mapStateToProps, null)(PrivateRouteComponent);
export default PrivateRoute

Private Route /log / / login loglog 。단, 예를 들어 하여 " " "를 사용합니다.<Redirect .../>의 " " " 를 클릭합니다<Link ...>URI를 사용합니다.같은 컴포넌트 상에 그대로 있습니다.

내가 뭘 잘못하고 있지?


★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.index.js을 사용하다루트는 다음과 같이 설정됩니다.

ReactDOM.render(
    <Provider store={store}>
        <App>
            <Router>
                <div>
                    <PrivateRoute exact path="/"><Home /></PrivateRoute>
                    // ... other private routes
                    <Route path="/login" component={Login} />
                </div>
            </Router>
        </App>
    </Provider>,
    document.getElementById('root')
);

포장해야 요.Route<Switch> 부착

ReactDOM.render(
<Provider store={store}>
    <App>
        <Router>
            <div>
                <Switch>
                   <PrivateRoute exact path="/"><Home /></PrivateRoute>
                   // ... other private routes
                   <Route path="/login" component={Login} />
                </Switch>
            </div>
        </Router>
    </App>
</Provider>,
document.getElementById('root'));

개인 루트를 순수하지 않게 설정합니다.

export default connect(mapStateToProps, null, null, {
  pure: false,
})(PrivateRoute);

그러면 컴포넌트가 다시 렌더링됩니다.

react-router-4-x-privateroute-not-working-after-to-redux 를 참조해 주세요.

같은 문제가 있어서 앱 리덕스 컨테이너를 만들고 isAuthenticated를 PrivateRoute에 전달함으로써 해결했습니다.

여기 있습니다. 도움이 되었으면 합니다.

const App = (props) => {
return (
  <Provider store={store}>
    <Router>
      <div>
        <PrivateRoute path="/secured" component={Secured} isAuthenticated={props.isAuthenticated} />
      </div>
    </Router>
  </Provider>
  );
};

const mapStateToProps = state => ({
  isAuthenticated: state.isAuthenticated
});

export default connect(mapStateToProps)(App);

그러면 Private Route에서

const PrivateRoute = ({ component: Component, isAuthenticated, ...rest}) => (
<Route
  {...rest}
  render={props => (
    isAuthenticated
    ? (
       <Component {...props} />
    )
    : (<Redirect to={{ pathname: '/login', state: { from: props.location} }} />)
  )}
/>
);

export default PrivateRoute;

은 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★rest에서 위한 mapStateToProps:

const PrivateRoute = ({component: Component, ...rest}) => {
  const {isAuthenticated} = rest;

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

PrivateRoute.propTypes = {
  isAuthenticated: PropTypes.bool.isRequired,
};

function mapStateToProps(state) {
  return {
    isAuthenticated: state.user.isAuthenticated,
  };
}

export default connect(mapStateToProps)(PrivateRoute);

이 질문에 대한 답은 좀 더 자세히 나와야 할 것 같아서, 4시간 동안 파헤친 끝에 여기 왔습니다.

connect로 컴포넌트를 랩하면 React Redux가 should ComponentUpdate(github 문제에 대한 답변을 검색하는 경우 sCU)를 구현하고 소품에서 얕은 비교를 수행합니다(소품 개체의 각 키를 통해 값이 '==='와 동일한지 확인합니다).실제로는 성분이 순수 성분으로 간주된다는 것을 의미합니다.이제 소품이 바뀌어야 바뀌어요!이것이 여기서의 핵심 메시지입니다.두 번째 키 메시지인 React router는 컨텍스트와 연계하여 라우터에서 Route 컴포넌트로 위치, 일치 및 이력 객체를 전달합니다.그것은 소품을 사용하지 않는다.

실제로 어떤 일이 일어나는지 봅시다.그것을 알면서도, 아직 꽤 까다롭기 때문입니다.

  • 케이스 1:

연결 후 소품에는 경로, 컴포넌트 및 인증(연결에 의해 지정됨)의 3가지 키가 있습니다.따라서 실제로 포장된 컴포넌트는 신경 쓰지 않기 때문에 경로 변경 시 재렌더링되지 않습니다.루트가 변경되어도 소품은 변경되지 않고 갱신되지 않습니다.

  • 케이스 3:

접속 후 소품에는 패스, 컴포넌트, auth, anyprop의 4가지 키가 있습니다.여기서 중요한 것은 anyprop은 컴포넌트가 호출될 때마다 생성되는 오브젝트라는 것입니다.따라서 구성 요소가 호출될 때마다 이 비교가 수행됩니다. {a:1} === {a:1}. 이 비교는 잘못된 정보를 제공하므로 이제 구성 요소가 매번 업데이트됩니다.단, 컴포넌트는 여전히 경로에 관심이 없으며, 그 하위 컴포넌트는 경로에 관심이 없습니다.

  • 케이스 2:

이것이 미스터리입니다.왜냐하면 앱 파일에서 이 행을 호출하고, 거기에 "auth"에 대한 참조가 없어야 하며, 오류가 있을 것입니다(적어도 그것이 제가 의도한 것입니다).앱 파일의 "auth"가 정의된 개체를 참조하는 것 같습니다.

이제 우리는 무엇을 해야 할까?

여기에는 다음 두 가지 옵션이 있습니다.

  1. React Redux에게 구성 요소가 순수하지 않다고 말합니다. 그러면 SCU 주입이 제거되고 구성 요소가 올바르게 업데이트됩니다.

    connect(mapStateToProps, null, null, {pure: false})(PrivateRoute)

  2. With Router()를 사용하면 위치, 일치 및 이력 객체를 소품으로 컴포넌트에 삽입할 수 있습니다.내부적인 것은 알 수 없지만 Respect 라우터는 이러한 오브젝트를 변환하지 않기 때문에 루트가 변경될 때마다 프로포트가 변경되어 컴포넌트가 올바르게 갱신됩니다.이 부작용은 리액트 트리가 WithRouter와 Route로 오염되어 있다는 것입니다.

github 문제에 대한 참조:업데이트 차단 처리

여기서 알 수 있듯이 withRouter는 퀵픽스로서 권장되는 솔루션이 아닙니다.pure:false를 사용하는 것은 언급되지 않았기 때문에 이 수정이 얼마나 좋을지 모르겠습니다.

세 번째 솔루션을 찾았습니다만, 라우터를 사용하는 것보다 더 나은 솔루션인지는 불분명하지만 고차수가 높은 컴포넌트를 사용하고 있습니다.고차 컴포넌트를 Redux 스토어에 연결하면 루트가 렌더링 내용에 대해 전혀 신경 쓰지 않고 HOC에서 처리합니다.

import Notlogged from "./Notlogged";    
function Isloggedhoc({ wrap: Component, islogged, ...props }) {
      return islogged ? <Component {...props} /> : <Notlogged {...props} />;
    }

const mapState = (state, ownprops) => ({
      islogged: state.logged,
      ...ownprops
    });

export default connect(mapState)(Isloggedhoc);

앱.js에서

<Route path="/PrivateRoute" render={props => <Isloadedhoc wrap={Mycomponent} />} />

큐어 기능을 만들어 조금 줄일 수도 있습니다.

function isLogged(component) {
  return function(props) {
    return <Isloadedhoc wrap={component} {...props} />;
  };
}

이렇게 사용하면:

<Route path="/PrivateRoute" render={isLogged(Mycomponent)} />

저도 이 문제와 씨름해 왔습니다.이것이 저의 해결책입니다.

isAuthenticated를 모든 <PrivateRoute>컴포넌트에 전달하는 것이 아니라 <PrivateRoute> 자체의 스테이트에서 isAuthenticated를 취득하기만 하면 됩니다.

import React from 'react';
import {Route, Redirect, withRouter} from 'react-router-dom';
import {connect} from 'react-redux';

// isAuthenticated is passed as prop here
const PrivateRoute = ({component: Component, isAuthenticated , ...rest}) => {
    return <Route
        {...rest}
        render={
            props => {
                return isAuthenticated ?
                    (
                        <Component {...props} />
                    )
                    :
                    (
                        <Redirect
                            to={{
                                pathname: "/login",
                                state: {from: props.location}
                            }}
                        />
                    )
            }
        }
    />
};

const mapStateToProps = state => (
    {
        // isAuthenticated  value is get from here
        isAuthenticated : state.auth.isAuthenticated 
    }
);

export default withRouter(connect(
    mapStateToProps, null, null, {pure: false}
)(PrivateRoute));

타이프 스크립트

Typescript를 위한 솔루션을 찾고 있다면, 이렇게 작업하도록 했습니다.

const PrivateRoute = ({ component: Component, ...rest }: any) => (
    <Route
        {...rest}
        render={props =>
            localStorage.getItem("authToken") ? (
                <Component {...props} />
            ) : (
                    <Redirect
                        to={{
                            pathname: "/login",
                            state: { from: props.location }
                        }}
                    />
                )
        }
    />
);

<Router>
    <Switch>
        <PrivateRoute exact path="/home" component={Home} />
        <Route path="/login" component={Login} />
    </Switch>
</Router>

만약 당신이 수업을 만들어서 가고싶다면, 이런 식으로.

class PrivateRoute extends Route {
    render() {
        if (localStorage.getItem("authToken")) {
            return <Route {...this.props} />
        } else {
            return <Redirect
                to={{
                    pathname: "/login",
                    state: { from: this.props.location }
                }}
            />
        }
    }
}

리액트 라우터의 설명서에 의하면, 이 라우터를 포장하는 것만으로,connect와 기능하다.withRouter:

// before
export default connect(mapStateToProps)(Something)

// after
import { withRouter } from 'react-router-dom'
export default withRouter(connect(mapStateToProps)(Something))

이것은 나에게 효과가 있었고, 이 경우 루트에 따라 내 뷰가 업데이트되기 시작했다.

@Rein과 같은 문제가 있습니다.제 경우 Private Route는 원래 버전과 거의 비슷해 보이지만 Redx에만 접속하여 가짜 대신 사용하였습니다.원래의 예에서 인증합니다.

const PrivateRoute = ({ component: Component, auth, ...rest }) => (
  <Route
   {...rest}
   render={props =>
   auth.isAuthenticated
    ? <Component {...props} />
    : <Redirect to={{ pathname: "/login" }} />}
  />
);

 PrivateRoute.propTypes = {
  auth: PropTypes.object.isRequired,
  component: PropTypes.func.isRequired
 }

 const mapStateToProps = (state, ownProps) => {
  return {
     auth: state.auth
  }
};

export default connect(mapStateToProps)(PrivateRoute);

사용방법 및 결과:-

  1. 일하지 않고 일을 기대하고 있다
    • <PrivateRoute path="/member" component={MemberPage} />
  2. 작동하지만 이와 같이 사용하는 것은 바람직하지 않습니다.
    • <PrivateRoute path="/member" component={MemberPage} auth={auth} />
  3. 일해.일을 하기 위해서일 뿐이지, 전혀 사용하고 싶지 않다.여기서 이해하면 원래 Private Route를 Redx에 연결하면 Private Route가 작동하지 않도록 하기 위해 몇 가지 추가 소품(모든 소품)을 전달해야 합니다.아무나 행동에 대해 힌트주세요.이것이 저의 주된 관심사입니다.새로운 질문으로서
    • <PrivateRoute path="/member" component={MemberPage} anyprop={{a:1}} />

언급URL : https://stackoverflow.com/questions/43520498/react-router-private-routes-redirect-not-working

반응형