简体   繁体   English

反应路由器链接不是重新渲染组件

[英]React router link is not re-rendering component

I have build a profile page which should render the content of the component by getting the user_id from the URL using react router.我已经构建了一个配置文件页面,该页面应该通过使用反应路由器从 URL 获取 user_id 来呈现组件的内容。

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

This works quite fine.这工作得很好。

But....但....

If I open any profile page by changing the URL and then click on my menu item to bring me back to the current users profile page it won't re-render the content of the component.如果我通过更改 URL 打开任何配置文件页面,然后单击我的菜单项将我带回当前用户配置文件页面,它不会重新呈现组件的内容。 But the URL of the browser changes.但是浏览器的URL发生了变化。

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

Any idea how to solve this issue?知道如何解决这个问题吗?

Profilepage.js 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 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应用程序.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;

You didn't share the file where routes are, but if I understand when you change from /profile/1 to /profile/2 the component is not remounted.您没有共享路由所在的文件,但是如果我了解您从/profile/1更改为/profile/2时不会重新安装该组件。 Maybe, you need using key atribute with param ID used in the route path to achieve that:也许,您需要在路由路径中使用带有参数 ID 的键属性来实现:

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

When you change url directly from /profile/1 to /profile/2 the current route keeps the same, then component is not remounted.当您将 url 直接从/profile/1更改为/profile/2时,当前路由保持不变,则不会重新安装组件。 If you add the key attribute to your Route, ReactJs listens to key changes and force the remounting when they happen, in your case, when user_id changes from 1 to 2.如果您将密钥属性添加到您的路线,ReactJs 会侦听密钥更改并在它们发生时强制重新安装,在您的情况下,当user_id从 1 更改为 2 时。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM