[英]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.