4

我的 React 容器如下所示:

class App extends React.Component {
  componentDidMount() {       
    if (this.props.location && this.props.location.pathname != '/callback') {      
      userManager.getUser().then(response => {        
        if (!response || response.expired) {           
          userManager.signinRedirect();
        }  
        else{
          this.props.dispatch(userFound(response));
        }
      });
    }
  }
  render() {  
    return (
      <div>
        <Switch>          
          <PrivateRoute exact path="/" component={HomePage} user={this.props.user} />
          <PrivateRoute exact path="/dashboard" component={Dashboard} user={this.props.user} />
          <Route exact path="/callback" component={CallbackPage} />
          <Route component={NotFoundPage} />          
        </Switch>
      </div>
    );
  }
}

回调组件如下所示:

class CallbackPage extends React.Component {
  render() {
    // just redirect to '/' in both cases
    return (
      <CallbackComponent
        userManager={userManager}
        successCallback={() => this.props.dispatch(push("/"))}
        errorCallback={error => {
          this.props.dispatch(push("/"));
          console.error(error);
        }}
        >
        <div>Redirecting...</div>
      </CallbackComponent>
    );
  }
}

我的 Privateroute 如下所示:

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

export default PrivateRoute; 

我的商店看起来像:

export default function configureStore(initialState = {}, history) {

  const middlewares = [
    sagaMiddleware,
    routerMiddleware(history),
  ];
  const enhancers = [
    applyMiddleware(...middlewares),
  ];
  const composeEnhancers =
    process.env.NODE_ENV !== 'production' &&
    typeof window === 'object' &&
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
      ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
        // TODO Try to remove when `react-router-redux` is out of beta, LOCATION_CHANGE should not be fired more than once after hot reloading
        // Prevent recomputing reducers for `replaceReducer`
        shouldHotReload: false,
      })
      : compose;
  const store = createStore(
    createReducer(),
    fromJS(initialState),
    composeEnhancers(...enhancers)
  );
  store.runSaga = sagaMiddleware.run;
  store.injectedReducers = {}; 
  store.injectedSagas = {}; 
  loadUser(store, userManager);
  return store;
}

我的问题是:回调组件被调用了两次。我找不到它从哪里触发?第一次,它按预期进入成功函数,然后第二次,它将进入错误函数。然后页面冻结,浏览器中显示的 URL 是回调链接。我找不到为什么这个回调运行两次?有人可以帮我解决这个问题。我希望你理解这个问题。

此代码基于 redux-oidc 示例。请点击以下链接。 Redux-oidc 示例

4

1 回答 1

2

您的路由器和 redux 存储配置看起来不错。但是你不需要调用getUser你的componentWillMount. 您的应用程序应配置为仅在存在有效用户时才呈现路由。

一个可能的解决方案是使用render而不是componentWillMount这样:

render() {
  const routes = (
    <Switch>          
      <Route exact path="/" component={HomePage} user={this.props.user} />
      <Route exact path="/dashboard" component={Dashboard} user={this.props.user} />
      <Route exact path="/callback" component={CallbackPage} />
      <Route component={NotFoundPage} />          
    </Switch>
  );

  const loginPage = <LoginPage />; // <-- create a dedicated login page component where signinRedirect is called

  const isValidUserPresent = this.props.user && !this.props.user.expired;
  const isCallbackRouteRequested = this.props.location.pathname === '/callback';
  const shouldRenderRoutes = isValidUserPresent || isCallbackRouteRequested;

  return shouldRenderRoutes ? routes : loginPage;            
}
于 2018-05-27T03:37:12.890 回答