Url 变化,但组件未在 React Router v6 中渲染,有人能帮忙吗?

huangapple go评论57阅读模式
英文:

Url changed but component did not render in react router v6 anyone help me

问题

你已经创建了一个受保护的路由,当用户正确输入后,将登录页面更改为仪表板页面,一切都运行正常,但在登录后URL已更改但组件没有更改,仍然停留在登录页面。如何将组件更改为仪表板页面。

以下是翻译好的内容:

我已经在这个代码中创建了一个受保护的路由

import { useSelector } from "react-redux";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { RootState } from "src/store";

const ProtectedRoute = () => {
  const location = useLocation();
  //   const isToken = localStorage.getItem("token") !== "";
  const { isAuthenticated, loading } = useSelector(
    (state: RootState) => state.login
  );
  if (loading) return null;

  return isAuthenticated ? (
    <Outlet />
  ) : (
    <Navigate to="/login" replace state={{ from: location }} />
  );
};

export default ProtectedRoute;

检查登录并从本地存储中获取令牌,然后从登录更改链接到仪表板

    builder.addCase(login.fulfilled, (state, action) => {
      const isToken = localStorage.getItem("token") !== "";
      const Token = localStorage.getItem("token");
      history.push("/dashboard");
      return {
        ...state,
        loading: false,
        isAuthenticated: isToken,
        token: Token,
        ...action.payload,
      };
    });

检查路由路径并相应更改链接

      <BrowserRouter>
        <Routes>
          <Route element={<Login />} path="/login" />
          <Route path="/" element={<ProtectedRoute />}>
            <Route path="dashboard" element={<Dashboard />} />
          </Route>
        </Routes>
      </BrowserRouter>

希望这有助于解决您的问题。如果您的组件没有在登录后更改为仪表板页面,可能需要确保登录操作成功时将路由更改为仪表板页面,如上面的代码所示。

英文:

I have created a protected Route on this code

import { useSelector } from &quot;react-redux&quot;;
import { Navigate, Outlet, useLocation } from &quot;react-router-dom&quot;;
import { RootState } from &quot;src/store&quot;;

const ProtectedRoute = () =&gt; {
  const location = useLocation();
  //   const isToken = localStorage.getItem(&quot;token&quot;) !== &quot;&quot;;
  const { isAuthenticated, loading } = useSelector(
    (state: RootState) =&gt; state.login
  );
  if (loading) return null;

  return isAuthenticated ? (
    &lt;Outlet /&gt;
  ) : (
    &lt;Navigate to=&quot;/login&quot; replace state={{ from: location }} /&gt;
  );
};

export default ProtectedRoute;

check login and get token from localstorage and change link to dashboard from login

    builder.addCase(login.fulfilled, (state, action) =&gt; {
      const isToken = localStorage.getItem(&quot;token&quot;) !== &quot;&quot;;
      const Token = localStorage.getItem(&quot;token&quot;);
      history.push(&quot;/dashboard&quot;);
      return {
        ...state,
        loading: false,
        isAuthenticated: isToken,
        token: Token,
        ...action.payload,
      };
    });

**Check Route path and change link accordingly **

      &lt;BrowserRouter&gt;
        &lt;Routes&gt;
          &lt;Route element={&lt;Login /&gt;} path=&quot;/login&quot; /&gt;
          &lt;Route path=&quot;/&quot; element={&lt;ProtectedRoute /&gt;}&gt;
            &lt;Route path=&quot;dashboard&quot; element={&lt;Dashboard /&gt;} /&gt;
          &lt;/Route&gt;
        &lt;/Routes&gt;
      &lt;/BrowserRouter&gt;

I want to make a protected route and change login page to dashboard page when user enter correctly and everything is working perfectly but after login the url change but component did not change it will stay on login page how to change compoent to dashboard page.

答案1

得分: 0

我怀疑你已经在你的状态切片中创建了一个单独的history对象引用,例如createBrowserHistory,并且正在使用它来尝试导航。这显然会更新URL,但因为这发生在主应用程序路由组件之外,所以它不知道URL的更改,不会重新渲染以匹配正确的路由。

Reducer函数应被视为纯函数,没有副作用,请不要尝试从Reducer中发出导航操作。由于login是一个异步操作,您可以在UI中使用await来执行它,并在那里发出导航操作。

示例:

Thunk操作

const login = createAsyncAction(
  "login",
  async ({ username, password }, thunkAPI) => {
    try {
      const result = fetch(.....);
      return /* auth result */
    } catch(error) {
      return thunkAPI.rejectWithValue(error);
    }
  },
);

...
 
builder.addCase(login.fulfilled, (state, action) => {
  const token = localStorage.getItem("token");

  return {
    ...state,
    loading: false,
    isAuthenticated: !!token,
    token,
    ...action.payload,
  };
});
...

登录界面

import { useNavigate } from 'react-router-dom';

...

const navigate = useNavigate();
const dispatch = useDispatch();

const loginHandler = async () => {
  try {
    await dispatch(login({ username, password })).unwrap();
    navigate("/dashboard"); // <--- 登录后在这里导航
  } catch(error) {
    // 处理登录错误、拒绝的Promises等
  }
};

...
英文:

What I suspect you have done is to create a separate history object reference in your state slice, e.g. createBrowserHistory, and are using that to try and navigate. This will obviously update the URL but because this happens outside the main app router component it isn't aware of the URL change and won't rerender with the correct route matched.

Reducer functions are to be considered pure and free of side-effects, don't try to issue a navigation action from the reducer. Since login is an asynchronous action you can await it in the UI and issue the navigation action there.

Example:

Thunk action

const login = createAsyncAction(
  &quot;login&quot;,
  async ({ username, password }, thunkAPI) =&gt; {
    try {
      const result = fetch(.....);
      return /* auth result */
    } catch(error) {
      return thunkAPI.rejectWithValue(error);
    }
  },
);

...
 
  builder.addCase(login.fulfilled, (state, action) =&gt; {
    const token = localStorage.getItem(&quot;token&quot;);

    return {
      ...state,
      loading: false,
      isAuthenticated: !!token,
      token,
      ...action.payload,
    };
  });
...

Login UI

import { useNavigate } from &#39;react-router-dom&#39;;

...

const navigate = useNavigate();
const dispatch = useDispatch();

const loginHandler = async () =&gt; {
  try {
    await dispatch(login({ username, password })).unwrap();
    navigate(&quot;/dashboard&quot;); // &lt;-- navigate here after login resolves
  } catch(error) {
    // handle login errors, rejected Promises, etc
  }
};

...

huangapple
  • 本文由 发表于 2023年8月5日 01:50:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76838164.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定