簡體   English   中英

始終重定向到當前路線而不是所需路線

[英]Always redirected to current route instead of desired route

我正在使用三元運算符來使用反應路由渲染組件。 但即使條件符合預期,我也總是被重定向到“/”路由而不是所需的組件。

只有當我刷新/重新加載頁面時,我才能獲得所需的功能。

這是我的 App.js 和所有路線

import React, { useEffect, useState } from 'react';
import Header from './Components/Header';
import Home from './Components/Home';
import Checkout  from "./Components/Checkout";
import Payment from "./Components/Payment";
import NewProduct from "./Components/NewProduct";
import OrderSuccess from "./Components/OrderSuccess";
import AddressForm from './Components/AddressForm';
import {BrowserRouter, Switch, Route} from "react-router-dom";
import { Redirect } from 'react-router';
import Login from './Components/Login';
import Orders from "./Components/Orders";
import Account from './Components/Account';
import { connect } from 'react-redux';

const App=()=>{

  const user = (JSON.parse(localStorage.getItem("profile")));

  const defaultRoutes= ()=>{
    return(
      <div>
    <Header/>
    <Switch>
    <Route  path="/account-settings" exact component={()=>user ? <Account />: <Redirect to="/" />} />
    <Route  path="/orders" exact component={()=>user ? <Orders /> : <Redirect to="/" />} />
    <Route  path="/checkout" exact component={()=>user ? <Checkout />: <Redirect to="/" />} />
    <Route  path="/payment" exact component={()=>user ? <Payment /> : <Redirect to="/" />} />
    <Route  path="/account-settings/add-new-address" exact component={()=>user?.result ? <AddressForm /> : <Redirect to="/" />} />
    <Route  path="/" exact component={Home} />
    </Switch>
    </div>
    )
  }

  return (
    <BrowserRouter>
    <Switch>
    <Route  path="/login" exact component={()=>user ? <Redirect to="/" />:<Login />} />
    <Route component={defaultRoutes} />
    </Switch>
    </BrowserRouter>
  );
}

export default App;

這是我的 index.js 文件

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { Provider } from "react-redux";
import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import "./index.css"
import reducers from "./reducers/index";

const store = createStore(reducers,{},compose(applyMiddleware(thunk)));

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>
    , document.getElementById("root")
)

這是我更新本地存儲的減速器

export default (state={authData:null},action)=>{
    switch(action.type){
        case "AUTH":
            localStorage.setItem("profile",JSON.stringify({...action?.data}));
            return {...state, authData: action.data, loading: false, errors: null};
        
        case "LOGOUT":
        localStorage.clear();
        return {...state,authData:null};   
        
        default:
            return "";    
    }
}

問題

你很近。 這里的問題是,即使您將身份驗證存儲在 localStorage 中更新 redux 狀態, App也不會被重新渲染以從 localStorage 中“獲取”新的auth值。

解決方案

  1. 從 localStorage 初始化 redux 狀態。
  2. 從您的 Redux 存儲中選擇身份驗證狀態。 這就是對 store 的更改觸發訂閱組件重新渲染的原因。

認證減速器

const initialState={
  authData:JSON.parse(localStorage.getItem("profile")),
  loading:false,
  errors:null
};

export default (state = initialState, action) => {
  switch(action.type){
    case "AUTH":
      localStorage.setItem("profile", JSON.stringify({ ...action?.data }));
      return {
        ...state,
        authData: action?.data,
        loading: false,
        errors: null
      };

    case "LOGOUT":
      localStorage.clear();
      return { ...state, authData: null };

    default:
      return state;
  }
};

應用程序

import { useSelector } from "react-redux";

const App = () => {

  const user = useSelector(state => state.auth.authData);

  const defaultRoutes = () => {
    return (
      <div>
        <Header/>
        <Switch>
          <Route
            path="/account-settings"
            render={() => user ? <Account />: <Redirect to="/" />}
          />
          <Route
            path="/orders"
            render={() => user ? <Orders /> : <Redirect to="/" />}
          />
          <Route
            path="/checkout"
            render={() => user ? <Checkout />: <Redirect to="/" />}
          />
          <Route
            path="/payment"
            render={() => user ? <Payment /> : <Redirect to="/" />}
          />
          <Route
            path="/account-settings/add-new-address"
            render={() => user?.result ? <AddressForm /> : <Redirect to="/" />}
          />
          <Route path="/" component={Home} />
        </Switch>
      </div>
    )
  };

  return (
    <BrowserRouter>
      ...
    </BrowserRouter>
  );
}

建議

查看身份驗證工作流並創建一個PrivateRoute組件來為您處理重定向。

例子:

const PrivateRoute = props => {
  const user = useSelector(state => state.auth.authData);

  return user ? <Route {...props} /> : <Redirect to="/" />
};

用法:

const App = () => {

  const defaultRoutes = () => {
    return (
      <div>
        <Header/>
        <Switch>
          <PrivateRoute path="/account-settings" component={Account} />
          <PrivateRoute path="/orders" component={Orders} />
          <PrivateRoute path="/checkout" component={Checkout} />
          <PrivateRoute path="/payment" component={Payment} />
          <Route
            path="/account-settings/add-new-address"
            render={() => user?.result ? <AddressForm /> : <Redirect to="/" />}
          />
          <Route path="/" component={Home} />
        </Switch>
      </div>
    )
  };

  return (
    <BrowserRouter>
      ...
    </BrowserRouter>
  );
}

刪除路由器中的三元。 如果不滿足條件,請使用useHistory重定向到"/" 為了檢查條件,創建一個名為useCheckUser的自定義鈎子,用於檢查localStorage是否有用戶。

在需要user每個組件中,

import useCheckUser from "file-address"
import { useHistory } from "react-router"


const Component = () => {
  let history = useHistory();
  let user = useCheckUser();
  if (!user) {
    history.push("/");
  }

  return ()

}

useCheckUser鈎子應該類似於


const useCheckUser = () => {
  let user = localStorage.getItem("profile");
  if (user) {
    return JSON.parse(user);
  }
  return null;
};

export default useCheckUser;

注意:如果您的唯一要求是在用戶存在時呈現組件,您可以更改自定義鈎子,使其執行包括重定向在內的所有操作。 這只是為了返回當前user 因此,如果您想在且僅當user不存在時呈現某些組件(如身份驗證頁面),則可以使用此方法。

嘗試為用戶獲取一個狀態(useState),並將其設置在 useEffect 中,如下所示:

 const [user, setUser] = useState(null);

  useEffect(() => {
   setUser(localStorage.getItem("profile"))
  }, [])

它會將“用戶”設置為您的頁面呈現

 function App() {
      const [user, setUser] = useState(null);

  useEffect(() => {
   setUser(localStorage.getItem("profile"))
  }, [])
    
    const authentication = {
        getLogInStatus() {
          return user;
        },
      };
    }
    
      function SecuredRoute(props) {
        return (
          <Route
            path={props.path}
            render={(data) =>
              authentication.getLogInStatus() ? (
                <props.component
                  {...data}
                ></props.component>
              ) : (
                handleRedirect()
              )
            }
          ></Route>
        );
      }
    
      const handleRedirect = () => {
        let login = window.confirm(
          "please Register or log in to access this page!"
        );
        if (login) {
          return <Redirect path="/"></Redirect>;
        }
      };
    
     return (
     <BrowserRouter>
     <Switch>
    // those routes which don't needs authetication
    <Route path="/home" compponent={Home} />
    <Route path="/login" compponent={Login} />
    //and others
    // those routes which needs authetication 
      <SecuredRoute path="/bookings" component={Bookings} />
      <SecuredRoute
                    path="/booking-details"
                    component={BookingDetails}
                  />
                  <SecuredRoute path="/favorites" component={Favorites} />
                  <SecuredRoute path="/profile" component={Profile} />
     </Switch>
     </BrowserRouter>
    
     );
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM