私有路由的最佳实践是什么?也许我做错了什么,但当用户登录时,我已经被重定向到/login页面

我的第二个问题是:这些版本中哪一个更好,或者你有更好的 idea ?

代码:

认证

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
  }
})

CASE 1:

应用程序

function 应用程序() {
  const dispatch = useDispatch()

  useEffect(() => {
    dispatch(me())
  }, [])

  const auth = useSelector((state) => state.auth)

  return (
    <div data-theme={theme}>
      <BrowserRouter>
        <应用程序路由 is认证enticated={auth.isUserLoggedIn} />
      </BrowserRouter>
    </div>
  )
}

export default 应用程序

路由

export const 应用程序路由 = ({ is认证enticated }) => (
  <路由>
    <Route
      path='/login'
      element={<Login />}
    />
    <Route
      path='/dashboard'
      element={
        <私密路由 is认证enticated={is认证enticated}>
          <Stats />
        </私密路由>
      }
    />
    ...

私密路由

export const 私密路由 = ({ children, is认证enticated }) => {
  return is认证enticated ? children : <Navigate to='/login' />
}

CASE 2:

应用程序

function 应用程序() {
  return (
    <div data-theme={theme}>
      <BrowserRouter>
        <应用程序路由 />
      </BrowserRouter>
    </div>
  )
}

export default 应用程序

路由

export const 应用程序路由 =  () => (
  <路由>
    <Route
      path='/login'
      element={<Login />}
    />
    <Route
      path='/dashboard'
      element={
        <私密路由>
          <Stats />
        </私密路由>
      }
    />
  ...

私密路由

export const 私密路由 = ({ 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更适合处理,或者你有更好的 idea ?

对于这两个 idea ,当我转到/dashboard时,它会很快重定向到/login

我想要实现的是良好的实践、快速的验证,并等待我们从后端收到用户经过身份验证的肯定响应

团队,你有什么建议?

EDIT

新版本:

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
  }
})

私密路由

export const 私密路由 = ({ children }) => {
  const dispatch = useDispatch()
  const { isLoading, isUserLoggedIn } = useSelector((state) => state.auth)

  if (isLoading) return null 

  return isUserLoggedIn ? (
    children
  ) : (
    <Navigate
      to='/login'
      replace
    />
  )
}

应用程序

function 应用程序() {
  const dispatch = useDispatch()
  const { isUserLoggedIn } = useSelector((state) => state.auth)

  useEffect(() => {
    if (isUserLoggedIn === null) {
      dispatch(me())
    }
  }, [])

  return (
    <div data-theme={theme}>
      <BrowserRouter>
        <应用程序路由 />
      </BrowserRouter>
    </div>
  )
}

export default 应用程序

Store

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}>
        <应用程序 />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')

但是当我重新加载页面时,我会转到/login,不要停留在同一页面上,比如/dashboard,我该怎么处理呢?

推荐答案

我发现了一个问题!哈哈!

看起来很愚蠢&&;简单,但它开始起作用->;

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) => { // <- {} replaced to _ and this is it! 
  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
  }
})

Reactjs相关问答推荐

react 表复选框不对任何操作做出react

值在返回页面时不更新,即使我已经更新了它们

为多租户SSO登录配置Azure AD应用程序

使用REACT-RUTER-DOM链接仅更新一个搜索参数

Reaction Google Maps API无法获取标题

用于获取带有事件处理程序的API的动态路由

StrictMode+SetInterval=双重渲染(即使使用useEffect清理)

如何测试根据 prop 更改 CSS 属性的 useEffect 钩子?

如何在 React Native 中渲染下面的对象数组?

如何将 npm 包添加到我的 Vite + React 应用程序中?

useMemo 依赖项的行为

React Router 6 点击链接在 React 18 应用中打开 flickr 页面

useState数组不更新

如何在 React 过滤器中包含价格过滤器逻辑?

在 reactJS 中导航时页面重新加载

当 React 中的状态发生变化时如何停止重新加载谷歌 map ?

来自一个自定义 React Native 组件的样式从另一个自定义组件移除样式

Storybook - 无法解析generated-stories-entry.cjs/字段browser不包含有效的别名配置

如何在react 日历中自定义带有圆形边框的日期项?

Lodash 在命名导入中导入整个包