私有路由的最佳实践是什么?也许我做错了什么,但是当用户登录时,我已经重定向到 /login 页面。
我的第二个问题是:以下哪个版本更好,或者你甚至有更好的想法?
代码:
认证
const authSlice = createSlice({
name: 'auth',
initialState: {
user: {},
isUserLoggedIn: null,
isLoading: false,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(me.pending, (state) => {
state.isLoading = true
})
.addCase(me.fulfilled, (state, action) => {
state.user = action.payload.userData
state.isUserLoggedIn = true
state.isLoading = false
})
.addCase(me.rejected, (state) => {
state.isUserLoggedIn = false
})
},
})
export const me = createAsyncThunk('auth/me', async () => {
try {
const user = await userService.getUserData()
return { userData: user.data.data }
} catch (error) {
const message =
(error.response && error.response.data && error.response.data.message) ||
error.message ||
error.toString()
return message
}
})
案例1:
应用程序
function App() {
const dispatch = useDispatch()
useEffect(() => {
dispatch(me())
}, [])
const auth = useSelector((state) => state.auth)
return (
<div data-theme={theme}>
<BrowserRouter>
<AppRoutes isAuthenticated={auth.isUserLoggedIn} />
</BrowserRouter>
</div>
)
}
export default App
路由
export const AppRoutes = ({ isAuthenticated }) => (
<Routes>
<Route
path='/login'
element={<Login />}
/>
<Route
path='/dashboard'
element={
<PrivateRoute isAuthenticated={isAuthenticated}>
<Stats />
</PrivateRoute>
}
/>
...
私有路由
export const PrivateRoute = ({ children, isAuthenticated }) => {
return isAuthenticated ? children : <Navigate to='/login' />
}
案例2:
应用程序
function App() {
return (
<div data-theme={theme}>
<BrowserRouter>
<AppRoutes />
</BrowserRouter>
</div>
)
}
export default App
路由
export const AppRoutes = () => (
<Routes>
<Route
path='/login'
element={<Login />}
/>
<Route
path='/dashboard'
element={
<PrivateRoute>
<Stats />
</PrivateRoute>
}
/>
...
私有路由
export const PrivateRoute = ({ children }) => {
const dispatch = useDispatch()
const { isUserLoggedIn } = useSelector((state) => state.auth)
useEffect(() => {
if (isUserLoggedIn === null) {
dispatch(me())
}
}, [])
return isUserLoggedIn ? children : <Navigate to='/login' />
}
CASE 1或CASE 2哪个更好,或者你有更好的想法吗?
对于这两个想法,在我进入/仪表板时,它会非常快速地重定向到/登录。
我的目标是良好的实践、快速验证,并等待我们从后端收到用户已经通过身份验证的积极响应。
团队,你们有什么建议?
编辑:
新版本:
Redux
const authSlice = createSlice({
name: 'auth',
initialState: {
user: {},
isUserLoggedIn: null,
isLoading: true,
},
reducers: {},
extraReducers: (builder) => {
builder
.addCase(me.pending, (state) => {
state.isLoading = true
})
.addCase(me.fulfilled, (state, action) => {
state.user = action.payload.userData
state.isUserLoggedIn = true
state.isLoading = false
})
.addCase(me.rejected, (state) => {
state.isLoading = false
state.isUserLoggedIn = false
})
},
})
export const me = createAsyncThunk('auth/me', async ({}, thunkAPI) => {
try {
const user = await userService.getUserData()
return { userData: user.data.data }
} catch (error) {
const message =
(error.response && error.response.data && error.response.data.message) ||
error.message ||
error.toString()
thunkAPI.rejectWithValue(message)
return message
}
})
PrivateRoute
export const PrivateRoute = ({ children }) => {
const dispatch = useDispatch()
const { isLoading, isUserLoggedIn } = useSelector((state) => state.auth)
if (isLoading) return null
return isUserLoggedIn ? (
children
) : (
<Navigate
to='/login'
replace
/>
)
}
应用程序
function App() {
const dispatch = useDispatch()
const { isUserLoggedIn } = useSelector((state) => state.auth)
useEffect(() => {
if (isUserLoggedIn === null) {
dispatch(me())
}
}, [])
return (
<div data-theme={theme}>
<BrowserRouter>
<AppRoutes />
</BrowserRouter>
</div>
)
}
export default App
存储
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit'
import authReducer from '../features/auth/authSlice'
export const store = configureStore({
reducer: {
auth: authReducer,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ serializableCheck: false }),
})
Index.js
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
但是当我重新加载页面时,会跳转到
/login
,而不是停留在/dashboard
这个页面,我该怎么解决这个问题?