当我尝试在新标签页中加载页面时,React Router 重定向到 BASE_URL

时间:2021-04-03 22:12:33

标签: reactjs django react-redux react-router django-react

我一直在做一个 React 项目,大约 4 天前我遇到了一个问题。当我尝试在新选项卡中打开链接时,它会重定向到 home/BASE url。我需要帮助修复错误。

渲染路由方法

export const renderRoutes = (routes = []) => (
  <Suspense fallback={<Loader />}>
    <Switch>
      {routes.map((route, i) => {
        const Guard = route.guard || Fragment;
        const Layout = route.layout || Fragment;
        const Component = route.component;

        return (
          <Route
            key={i}
            path={route.path}
            exact={route.exact}
            render={(props) => (
              <Guard>
                <Layout>
                  {route.routes
                    ? renderRoutes(route.routes)
                    : <Component {...props} />}
                </Layout>
              </Guard>
            )}
          />
        );
      })}
    </Switch>
  </Suspense>
);

Picture of Guest Route

Picture of the Admin Route

GuestGuard

const GuestGuard = (props) => {
  console.log(props, BASE_URL)
  if (props.isLoggedIn) {
    console.log(BASE_URL)
    return <Redirect to={BASE_URL} />;
  }

  return (
    <React.Fragment>
      {props.children}
    </React.Fragment>
  );
};

GuestGuard.propTypes = {
  isLoggedIn: PropTypes.bool.isRequired
}

const mapStateToProps = (state) => ({
  isLoggedIn: state.auth.isLoggedIn
})

export default connect(mapStateToProps, )(GuestGuard);

AuthGuard

const AuthGuard = ({ children, isLoggedIn }) => {
    // console.log(children, 393)
    if (!isLoggedIn) {
        return <Redirect to="/auth/signin-1" />;
    }
    console.log("LOGGED IN", children.props)
    return (
        <React.Fragment>
            {children}
        </React.Fragment>
    );
};

AuthGuard.propTypes = {
    isLoggedIn: PropTypes.bool.isRequired
  }

const mapStateToProps = (state) => ({
    isLoggedIn: state.auth.isLoggedIn
})

export default connect(mapStateToProps, )(AuthGuard);

应用(提供者来自 react-redux)

const App = () => {
  useEffect(() => {
    store.dispatch(init());
  }, [])
  return (
    <Provider store={store}>    
        <Router basename={BASENAME}>          
          <React.Fragment>
            {renderRoutes(routes)}            
          </React.Fragment>
        </Router>
    </Provider>
  );
};

export default App;

在useEffect中调用的init方法

export const init = () => (dispatch) => {
    try {
      const serviceToken = window.localStorage.getItem('serviceToken');        
      if (serviceToken) {
        setSession(serviceToken);
        axios.get('http://localhost:8000/api/auth/user', tokenConfig())
        .then(response => {         
          const user = response.data;
          dispatch({
            type: ACCOUNT_INITIALISE,
            payload: {
              isLoggedIn: true,
              user
            }
          })
        }).catch(err=>{
          dispatch({
            type:LOGOUT
          })
        })
      } else {
        dispatch({
          type: ACCOUNT_INITIALISE,
          payload: {
            isLoggedIn: false,
            user: null
          }
        });
      }
    } catch (err) {
      console.error(err);
      dispatch({
        type: ACCOUNT_INITIALISE,
        payload: {
          isLoggedIn: false,
          user: null
        }
      });
    }
  };

store(与 App.js 在同一个目录下)

import {createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from './reducers/index'

const initialState = {};

const middleware = [thunk];

const store = createStore(
    rootReducer,
    initialState,
    compose(
      applyMiddleware(...middleware),
      window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
    )
  );

export default store;

auth reducer

const initialState = {
  isLoggedIn: false,
  isInitialised: false,
  user: null
};
  
export default function (state = initialState, action) {
  switch (action.type) {
    case ACCOUNT_INITIALISE: {
        const { isLoggedIn, user } = action.payload;
        return {
            ...state,
            isLoggedIn,
            isInitialised: true,
            user
        };
    }
    case LOGIN: {
        const { user } = action.payload;
        return {
            ...state,
            isLoggedIn: true,
            user
        };
    }
    case LOGOUT: {
        localStorage.removeItem('serviceToken');
        return {
            ...state,
            isLoggedIn: false,
            user: null
        };
    }
    default: {
        return { ...state };
    }
}
  }

1 个答案:

答案 0 :(得分:1)

我认为您需要在此处调试应用程序流程。下面似乎是根本原因,当链接在新选项卡中打开时,它受 authGuard 保护,并且“useEffect 中调用的 init 方法”正在异步调用 api。因此 authGuard 第一次获取 isloggedIn false 并重定向到“/auth/signin-1”。同时, isloggedIn 设置为 true 并且 guestGuard 重定向到登录页面。

这里有以下选项: 除非您从 api 得到响应,否则不要加载您的路由器。收到响应时显示加载程序。

希望您在这里找到错误,这个答案可以帮助您修复相同的问题。