2

I am building a social network web app so i have multiple and different users and their profiles. I have a route for "/profile/:userId" in my Switch in my App.js file (and also in my backend obviously). I also have a NavLink button on my navigation bar for going to my profile. Users can also press on the username of someone's post and go to their profiles. All that work great but with one problem. When i am in a user's profile (not my profile) and click on "my profile" button from my navigation bar, even though the route changes (i.e. if i am user user1 and i am watching a random profile "/profile/user2" and press the profile button from my navigation bar, i go to route "/profile/user1" but the page does not re-render so i am still watching user's "user2" profile). So i want to trigger a reload if the parameters of the url change. Or at least that's what i though of. If you have a better idea of when to reload / re-render the page please share it with me. I am very new to react by the way so bear with me :D

I don't know exactly what part of my code i should upload along with my question to help so if you need any part of my code please tell me and i will upload it. the "profile" button on my navigation bar and also the username of any user on a post are both a Navlink.

the Navlink (which is the "username" of the user that uploaded the post) from my Post.js (the file responsible of every single post i am rendering):

<div className="Post-user-nickname">
  <NavLink className='Nav-link' to={'/profile/' + this.props.creator._id} user={this.props.creator}>{this.props.author}</NavLink>
</div>

the Navlink in my navigation bar:

item = { id: 'Profile', text: 'Profile', link: '/profile/' + this.props.userId, auth: true }

<NavLink to={item.link} exact onClick={this.props.onChoose}>
            {item.text}
</NavLink>

edit: my Profile.js componentDidMount:

  componentDidMount() {
    const userId = this.props.match.params.userId;
    this.setState({userIdNew: userId});
    console.log('-------------------- ' + userId);
    fetch('http://localhost:8080/feed/profile/' + userId, {
      headers: {
        Authorization: 'Bearer ' + this.props.token
      }
    })
      .then(res => {
        if (res.status !== 200) {
          throw new Error('Failed to fetch user status.');
        }
        return res.json();
      })
      .then(resData => {
        this.setState({ status: resData.status, user: resData.user });
        console.log('prwtos: ' + this.state.user._id);
        this.setState({
          posts: resData.user.posts.map(post => {
            return {
              ...post
            };
          })
        });
        this.setState({ imagePath: 'http://localhost:8080/' + resData.user.posts.map(post => {
          let imgUrl = post.imageUrl;
          return imgUrl;
        }) 
        });
        this.setState({ userImage: 'http://localhost:8080/' + resData.user.image })
      })
      .catch(this.catchError);
      this.loadPosts();
      this.loadFollowers();
      this.loadFollowing();
      const socket = openSocket('http://localhost:8080');
      socket.on('posts', data => {
        if (data.action === 'create') {
          this.addPost(data.post);
        } else if (data.action === 'update') {
          this.updatePost(data.post);
        } else if (data.action === 'delete') {
          this.loadPosts();
        }
      });
      this.setState({userIdNew: userId});
  }
gevor
  • 79
  • 3
  • 13
  • Are you using `reactjs` with `react-router`? If that so can you share the relative routes configuration? Your problem is usually solved detecting changes in props with `componentDidUpdate` – Tizio Fittizio Nov 28 '19 at 22:07
  • with `componentDidUpdate` i am not rendering the page the first time i want to see a profile. meaning if i click profile from the navigation bar i am getting an empty page. And if i click to see a profile again i am reloading (sending requests?) infinitely. as i said i am noob with react so maybe i do something wrong in my `componentDidUpdate`. but once i have the `componentDidMount` at least i am seeing the profile the first time i click to see a profile – gevor Nov 28 '19 at 22:13
  • Maybe you can share your current code in `componentDidMount` and in `componentDidUpdate`, basically, you obtain the current user from the url with the react router history props, if the route of your page is `/profile/:userId` than you can obtain the user id with `this.props.match.params.userId`, in `componentDidUpdate` you can then check if the user id is changed and subsequently perform another request – Tizio Fittizio Nov 28 '19 at 22:19
  • added my code in `componentDidMount` – gevor Nov 28 '19 at 22:25
  • possible duplicate of https://stackoverflow.com/questions/38915066/on-url-change-i-want-to-re-render-my-component-how-should-i-do-that/38916204 and https://stackoverflow.com/questions/52252353/re-render-same-component-on-url-change-in-react/53509329 – Andy Nov 03 '20 at 14:52

1 Answers1

2

Basically, you are performing the request in componentDidMount when the component (the page) is loaded, going to another profile it doesn't mean change page, you are changing props but the request is never reloaded, you could

  • Extract the request logic in another function that lives inside the component, something like fetchUser, this will use this.props.match.params.userId
  • In componentDidMount:

    • Call fetchUser
    • Save current user id in state
  • In componentDidUpdate:

    • You can check if the current user id in props is different from the one you saved in state (another profile is showed), if it is, you can call fetchUser again to obtain the new user data and retriggering a new render
Tizio Fittizio
  • 520
  • 5
  • 16
  • hmm ok. i will try it. the first two steps are clear. my question is in the third. do i have to have both `componentDidUpdate` and `componentDidMount` in my class? or do i replace my `componentDidMount`? – gevor Nov 28 '19 at 22:46
  • @gevor you are handling two events in your component: when it loads and when its props changes, so you should have both – Tizio Fittizio Nov 28 '19 at 22:48