【问题标题】:React router link is not re-rendering component反应路由器链接不是重新渲染组件
【发布时间】:2021-05-27 23:36:33
【问题描述】:

我已经构建了一个配置文件页面,该页面应该通过使用反应路由器从 URL 获取 user_id 来呈现组件的内容。

<PrivateRoute exact path='/profile/:user_id' component={ProfilePage} />

这很好用。

但是……

如果我通过更改 URL 打开任何个人资料页面,然后单击我的菜单项将我带回当前用户个人资料页面,它不会重新呈现组件的内容。 但是浏览器的网址发生了变化。

<Dropdown.Item
    as={Link}
    to={`/profile/${user.user_id}`}
    text='My profile'
  />

知道如何解决这个问题吗?

Profilepage.js

import { useSelector } from "react-redux";
import { deleteHotel, getHotelsByUserID } from "../../actions/hotel";
import { Grid, Segment } from "semantic-ui-react";
import ProfileHeader from "./ProfileHeader";
import ProfileContent from "./ProfileContent";
import { toast } from "react-toastify";
import { getProfileByCurrentUserID } from "../../actions/profile";

export default function ProfilePage({ match }) {
  const { auth } = useSelector((state) => ({ ...state }));
  const { token } = auth;
  const [hotels, setHotels] = useState([]);
  const [profile, setProfile] = useState("");

  useEffect(() => {
    loadAllHotel();
  }, []);

  useEffect(() => {
    loadProfile();
  }, []);

  const loadAllHotel = async () => {
    let res = await getHotelsByUserID(token, match.params.user_id);
    setHotels(res.data);
  };

  const loadProfile = async () => {
    let res = await getProfileByCurrentUserID(token, match.params.user_id);
    setProfile(res.data);
  };

  const handleHotelDelete = async (hotel_id) => {
    try {
      await deleteHotel(token, hotel_id);
      toast.success("Hotel deleted");
      loadAllHotel();
      loadProfile();
    } catch (err) {
      console.error(err);
      toast.error("Cannot delete hotel");
    }
  };

  return (
    <Grid>
      <Grid.Column width={16}>
        <Segment.Group>
          <ProfileHeader match={match} profile={profile} />
          <ProfileContent
            match={match}
            hotels={hotels}
            handleHotelDelete={handleHotelDelete}
          />
        </Segment.Group>
      </Grid.Column>
    </Grid>
  );
}

SignedInMenu.js

import { useDispatch } from "react-redux";
import { Link, useHistory } from "react-router-dom";
import { Image, Dropdown, Menu } from "semantic-ui-react";
import avatar from "../img/stevie.jpg";
import { useSelector } from "react-redux";

export default function SignedInMenu() {
  const dispatch = useDispatch();
  const history = useHistory();

  const { auth } = useSelector((state) => ({ ...state }));
  const { user } = auth;

  const logout = () => {
    console.log("LOGOUT");
    dispatch({
      type: "LOGOUT",
      payload: null,
    });
    window.localStorage.removeItem("auth");
    history.push("/signin");
  };
  return (
    <Menu.Item position='right'>
      <Image avatar spaced='right' src={avatar} />
      <Dropdown pointing='top left' text={user.user_name}>
        <Dropdown.Menu>
          <Dropdown.Item
            as={Link}
            to='/hotel/new'
            text='New Hotel'
            // icon='plus'
          />
          <Dropdown.Item
            as={Link}
            // to='/profile/me'
            to={`/profile/${user.user_id}`}
            text='My profile'
            // icon='user'
          />
          <Dropdown.Item
            // as={Link}
            // to='/placeholder'
            text='My account'
            // icon='user'
          />
          <Dropdown.Item text='Sign out' icon='power' onClick={logout} />
        </Dropdown.Menu>
      </Dropdown>
    </Menu.Item>
  );
}

App.js

import { BrowserRouter, Switch, Route, Redirect } from "react-router-dom";
import { useSelector } from "react-redux";
import { Container } from "semantic-ui-react";
import { ToastContainer } from "react-toastify";

// css
import "react-toastify/dist/ReactToastify.css";
import "./App.css";

// components
import NavBar from "./components/navigation/Navbar";
import PrivateRoute from "./components/PrivateRoute";
import Login from "./components/auth/Login";
import Register from "./components/auth/Register";
import HotelDashboard from "./components/hotels/HotelDashboarrd";
import NewHotel from "./components/hotels/NewHotel";
import ProfilePage from "./components/profiles/ProfilePage";
import ProfileStatistics from "./components/profiles/ProfileStatistics";

function App() {
  const { auth } = useSelector((state) => ({ ...state }));

  return (
    <BrowserRouter>
      <NavBar />
      <ToastContainer />
      <Switch>
        <>
          <Route exact path='/signin'>
            {auth ? <Redirect to='/home' /> : <Login />}
          </Route>
          <Route exact path='/signup'>
            {auth ? <Redirect to='/home' /> : <Register />}
          </Route>

          <Container className='main'>
            <PrivateRoute exact path='/home' component={HotelDashboard} />
            <PrivateRoute exact path='/hotel/new' component={NewHotel} />
            <PrivateRoute
              exact
              path='/profile/:user_id'
              component={ProfilePage}
            />
            <PrivateRoute
              exact
              path='/profile/statistics'
              component={ProfileStatistics}
            />
          </Container>
        </>
      </Switch>
    </BrowserRouter>
  );
}

export default App;

【问题讨论】:

    标签: reactjs react-router


    【解决方案1】:

    您没有共享路由所在的文件,但如果我理解当您从 /profile/1 更改为 /profile/2 时,组件不会重新安装。也许,您需要在路由路径中使用带有参数 ID 的键属性来实现:

    <PrivateRoute
      exact
      path='/profile/:user_id'
      component={(props) => (
        <ProfilePage
          {...props}
          key={props.match.params.user_id}
        />
      )}
    />
    

    当你将 url 直接从 /profile/1 更改为 /profile/2 时,当前路由保持不变,则不会重新安装组件。如果您将 key 属性添加到您的 Route,ReactJs 会侦听 key 更改并在它们发生时强制重新安装,在您的情况下,当 user_id 从 1 更改为 2 时。

    【讨论】:

    • 我已经编辑了我最初的评论。请看一看。
    • 好的。尝试删除包装您的私有路由的&lt;Container className='main'&gt;,并包含我在解决方案中解释的关键属性。
    • 我需要如何更改我的代码才能完成这项工作?如果我将 match.params.user_id 添加到我的 App.js 我将得到 undefined 。
    • 对不起,我现在在解决方案中进行了调整!
    • 完美。这行得通..你能不能用一些话来解释这个问题到底是什么,为什么以前没有解决。提前致谢。
    猜你喜欢
    • 2019-03-02
    • 1970-01-01
    • 2017-12-23
    • 2018-07-26
    • 1970-01-01
    • 2023-04-03
    • 2018-06-02
    • 1970-01-01
    • 2016-02-24
    相关资源
    最近更新 更多