Reputation: 576
I couldn't find the answer anywhere because nothing was working for me, so I'm starting a new topic. Please, don't mark it as a duplicate
<Switch>
<Route path="/" exact component={Home} />
<Route exact path="/p/:uid" component={Profile} />
</Switch>
constructor(props) {
super(props);
this.state = {
loading: true,
profile_user_id: this.props.match.params.uid,
};
}
Then, later in Profile.js, I trigger a fetch to get data from backend and save this data to state using this.setState({ ... }). When the Profile component is rendered, everything looks fine.
In Router.js, there is also a Link:
<Link to={"/p/" + this.state.ntuser.tag}>Profile</Link>
.. which should go to your own profile. So when your user ID is 1, and you visit the profile of the user with id 22, your URL will be /p/user22 and the link will point to /p/user1.
The problem is that even though profiles are rendered nicely, Profile component does not become re-rendered when you click the link (which should direct you to /p/user1 and show your profile instead). I tried to save location from react-router to state as well, so every time URL changes it will be caught in componentWillReceiveProps() and inside I update state. But still nothing. Any ideas?
PS: I'm using React.Component
Upvotes: 0
Views: 1184
Reputation: 8418
console.log(this.props.match.params.uid)
in constructor
, componentDidMount()
and componentDidUpdate()
(UNSAFE_componentWillReceiveProps()
is deprecated)
Number and places (of log calls) will tell you if component is recreated (many construcor calls) or updated (cDM calls). Move your data fetching call accordingly (into cDM or cDU ... or sCU).
You can save common data in component above <Router/>
(f.e. using context api) - but this shouldn't be required in this case.
You can update state from changed props using componentDidUpdate() or shouldComponentUpdate(). componentDidUpdate
should be protected with conditions to prevent infinite loop. See docs.
Simplest solution:
componentDidUpdate(prevProps) {
if (this.props.some_var !== prevProps.some_var) {
// prop (f.e. route '.props.match.params.uid') changed
// setState() - f.e. for 'loading' conditional rendering
// call api - use setState to save fetched data
// and clearing 'loading' flag
}
}
shouldComponentUpdate()
can be used for some optimalizations - minimize rerenderings.
Upvotes: 1
Reputation: 2459
Here is what happens:
<Route exact path="/p/:uid" component={Profile} />
.this.props.match.params.uid
is equal to "user22". Therefore, this.state.profile_user_id
is now "user22".<Route exact path="/p/:uid" component={Profile} />
, which is the same Route.This explains why you still see the profile of user22
Upvotes: 0
Reputation: 166
Had same problem in my project, Didn't find any good workable idea exept making somethink like this:
import {Profile} from "../Profile "
<Link to={`your href`}
onClick={userChanged}/>
..........
function userChanged() {
const userCard= new Profile();
userCard.getProfileData();
}
First of all you need to make your Profile component as export class Profile extends React.Component
(export without default).
getProfileData
is method where i get data from my api and put it state. This will rerender your app
Upvotes: 0