0

I have couple of react components and this question refers to specifically to two components: UserDetails and User, inside UserDetails I am rendering friends of the user, each of them is component User, so when I click one of their friend, in route, user id is changing but in reality I am rendering same component: UserDetails, and I am fetching data of this user but page is not scrolling up, can I fix it somehow?

Here is UserDetails

import React, {useEffect, useState} from 'react';
import {useParams} from 'react-router-dom';
import { Link } from 'react-router-dom';
import User from './User';
import { useDispatch, useSelector } from 'react-redux';
import { setSelectedUser, removeUser, setSelectedUsersHistory, setUserFriends, setFriendsPage, setFriendsLoading } from '../redux/actions/actions';
import '../styles/UserDetails.css';

export const UserDetails = () => {
    const selectedUser = useSelector(state => state.setSelectedUserReducer);
    const selectedUsersHistory = useSelector(state => state.setSelectedUsersHistoryReducer);
    const userFriends = useSelector(state => state.setUserFriendsReducer);
    const friendsPage = useSelector(state => state.setFriendsPageReducer);
    const friendsLoading = useSelector(state => state.setFriendsLoadingReducer);
    const [dynamicId, setDynamicId] = useState('');
    const dispatch = useDispatch();
    const {userId} = useParams();
    const fetchUserDetails = () => {
        fetch(`${url}/${userId}`)
            .then(res => res.json())
            .then(data => {
                 dispatch(setSelectedUser(data));
                 setDynamicId(userId)
              }
            )
            .catch(err => console.log('Error message: ', err))
    }

    const fetchUserFriends = () => {
        dispatch(setFriendsLoading(true));
        fetch(`${url}/${userId}/friends/${friendsPage}/15`)
            .then(res => res.json())
            .then(data => {         
                    dispatch(setUserFriends( data.list.filter(el => {
                        return el.id.toString() !== userId
                    })))
            })
            .catch(err => console.log('Error message: ', err))
            .finally(() => {
                dispatch(setFriendsLoading(false))
            })
    }

    useEffect(() => {
        if(userId && userId!=='') fetchUserDetails();
        
        return () => {
            dispatch(removeUser())
        }
    }, [userId])

    useEffect(() => {
        fetchUserFriends()
    }, [friendsPage])
  
      const handleScroll = () => {
          dispatch(setFriendsPage());
      }
  
      window.onscroll = function () {
          if(window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
              handleScroll();
          }
      }


    return (
        <div className="userDetails">
            {
                Object.keys(selectedUser).length === 0 ? (
                    <div>Loading...</div>
                ) : (
                <div className="user-about">
                <div className="user-details-image">
                    <img src={selectedUser.imageUrl} alt="user-image" />
                </div>

                <div className="user-info">
                    <fieldset>
                        <legend>Info</legend>
                        <div className="row1">
                            <h3>
                                 <span>{selectedUser.prefix} </span>
                                 <span>{selectedUser.name} </span>
                                 <span>{selectedUser.lastName} </span>
                            </h3>
                        </div>

                        <div className="row2">
                            <div className="personal-details">
                                <span className="email-label label">
                                    Email:
                                </span>

                                <span> </span>

                                <span className="email-data">
                                    {selectedUser.email}
                                </span>
                            </div>
                            <div className="personal-details">
                               <span className="ip-address-data label">
                                    IP Address: 
                                </span> 

                                <span> </span>

                                <span className="ip-address-data">
                                    {selectedUser.ip}
                                </span>
                            </div>
                            <div className="personal-details">
                            <span className="job-area-label label">
                                    Job Area:
                                </span>

                                <span> </span>

                                <span className="job-area-data">
                                    {selectedUser.jobArea}
                                </span>
                            </div>
                            <div className="personal-details">
                            <span className="job-type-label label">
                                    Job Type:
                                </span>

                                <span> </span>

                                <span className="job-type-data">
                                    {selectedUser.jobType}
                                </span>
                            </div>
                        </div>
                    </fieldset>
                </div>

                <div className="user-address">
                    <fieldset>
                        <legend>Address</legend>
                        <div className="address-info">
                                <h3>
                                    <span>{selectedUser.company.name}</span>
                                    <span>{selectedUser.company.suffix}</span>
                                </h3>

                                <div className="personal-details">
                                    <span className="city-label label">
                                        City:
                                    </span>

                                    <span> </span>

                                    <span className="city-data">
                                        {selectedUser.address.city}
                                    </span>
                                </div>

                                <div className="personal-details">
                                    <span className="country-label label">
                                        Country:
                                    </span>

                                    <span> </span>

                                    <span className="country-data">
                                        {selectedUser.address.country}
                                    </span>
                                </div>

                                <div className="personal-details">
                                    <span className="state-label label">
                                        State:
                                    </span>

                                    <span> </span>

                                    <span className="state-data">
                                        {selectedUser.address.state}
                                    </span>
                                </div>

                                <div className="personal-details">
                                    <span className="street-label label">
                                        Street Address:
                                    </span>

                                    <span> </span>

                                    <span className="street-data">
                                        {selectedUser.address.streetAddress}
                                    </span>
                                </div>

                                <div className="personal-details">
                                    <span className="zip-label label">
                                        ZIP:
                                    </span>

                                    <span> </span>

                                    <span className="zip-data">
                                        {selectedUser.address.zipCode}
                                    </span>
                                </div>
                        </div>
                    </fieldset>
                </div>
            </div>
                )
            }

            <div className="friends-list">
                    {
                        userFriends ? (
                            userFriends.map((friend, index) => (
                                <Link key={friend.id} to={`/user/${friend.id}`}>
                                    <User name={friend.name} lastName={friend.lastName} prefix={friend.prefix} title={friend.title} img={`${friend.imageUrl}/${friend.id}`}/>
                                </Link>
                            ))
                        ) : (
                             <div> Loading... </div>
                        )
                    }


                    {
                        friendsLoading ? <h1>Loaidng...</h1> : ''
                    }
            </div>
        </div>
    )
}

export default UserDetails;

Here is the User component:

import React, {useEffect} from 'react';
import '../styles/User.css';

const User = ({name, lastName, prefix, title, img}) => {
    return (
        <div className="user">
            <div className="user-image">
                <img src={`${img}/${Math.random()}`} alt="user-image" />
            </div>

            <div className="user-name">
                <span>{prefix} </span>
                <span>{name} </span>
                <span>{lastName} </span>
            </div>

            <div className="user-position">
                <span>{title}</span>
            </div>
        </div>
    )
}

export default React.memo(User);

nick1212
  • 5
  • 2
  • Hope this helps https://stackoverflow.com/questions/36904185/react-router-scroll-to-top-on-every-transition – Rahul Dec 16 '21 at 15:27
  • Unfortunately no, my issue is that, I am rendering same component but in url only id is changing – nick1212 Dec 16 '21 at 15:33

1 Answers1

0

You just need to use useMemo or useEffect to make the window scroll to the top when a variable's value (userId in this case) has been modified/changed. For example:

import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { Link } from "react-router-dom";
import User from "./User";
import { useDispatch, useSelector } from "react-redux";
import {
  setSelectedUser,
  removeUser,
  setSelectedUsersHistory,
  setUserFriends,
  setFriendsPage,
  setFriendsLoading,
} from "../redux/actions/actions";
import "../styles/UserDetails.css";

export const UserDetails = () => {
  const selectedUser = useSelector((state) => state.setSelectedUserReducer);
  const selectedUsersHistory = useSelector(
    (state) => state.setSelectedUsersHistoryReducer
  );
  const userFriends = useSelector((state) => state.setUserFriendsReducer);
  const friendsPage = useSelector((state) => state.setFriendsPageReducer);
  const friendsLoading = useSelector((state) => state.setFriendsLoadingReducer);
  const [dynamicId, setDynamicId] = useState("");
  const dispatch = useDispatch();
  const { userId } = useParams();
  const fetchUserDetails = () => {
    fetch(`${url}/${userId}`)
      .then((res) => res.json())
      .then((data) => {
        dispatch(setSelectedUser(data));
        setDynamicId(userId);
      })
      .catch((err) => console.log("Error message: ", err));
  };

  const fetchUserFriends = () => {
    dispatch(setFriendsLoading(true));
    fetch(`${url}/${userId}/friends/${friendsPage}/15`)
      .then((res) => res.json())
      .then((data) => {
        dispatch(
          setUserFriends(
            data.list.filter((el) => {
              return el.id.toString() !== userId;
            })
          )
        );
      })
      .catch((err) => console.log("Error message: ", err))
      .finally(() => {
        dispatch(setFriendsLoading(false));
      });
  };

  useEffect(() => {
    if (userId && userId !== "") {
      fetchUserDetails();
      window.scrollTo({ top: 0, left: 0, behavior: "smooth" });
    }

    return () => {
      dispatch(removeUser());
    };
  }, [userId]);

  useEffect(() => {
    fetchUserFriends();
  }, [friendsPage]);

  const handleScroll = () => {
    dispatch(setFriendsPage());
  };

  window.onscroll = function () {
    if (
      window.innerHeight + document.documentElement.scrollTop ===
      document.documentElement.offsetHeight
    ) {
      handleScroll();
    }
  };

  return (
    <div className="userDetails">
      {Object.keys(selectedUser).length === 0 ? (
        <div>Loading...</div>
      ) : (
        <div className="user-about">
          <div className="user-details-image">
            <img src={selectedUser.imageUrl} alt="user-image" />
          </div>

          <div className="user-info">
            <fieldset>
              <legend>Info</legend>
              <div className="row1">
                <h3>
                  <span>{selectedUser.prefix} </span>
                  <span>{selectedUser.name} </span>
                  <span>{selectedUser.lastName} </span>
                </h3>
              </div>

              <div className="row2">
                <div className="personal-details">
                  <span className="email-label label">Email:</span>

                  <span> </span>

                  <span className="email-data">{selectedUser.email}</span>
                </div>
                <div className="personal-details">
                  <span className="ip-address-data label">IP Address:</span>

                  <span> </span>

                  <span className="ip-address-data">{selectedUser.ip}</span>
                </div>
                <div className="personal-details">
                  <span className="job-area-label label">Job Area:</span>

                  <span> </span>

                  <span className="job-area-data">{selectedUser.jobArea}</span>
                </div>
                <div className="personal-details">
                  <span className="job-type-label label">Job Type:</span>

                  <span> </span>

                  <span className="job-type-data">{selectedUser.jobType}</span>
                </div>
              </div>
            </fieldset>
          </div>

          <div className="user-address">
            <fieldset>
              <legend>Address</legend>
              <div className="address-info">
                <h3>
                  <span>{selectedUser.company.name}</span>
                  <span>{selectedUser.company.suffix}</span>
                </h3>

                <div className="personal-details">
                  <span className="city-label label">City:</span>

                  <span> </span>

                  <span className="city-data">{selectedUser.address.city}</span>
                </div>

                <div className="personal-details">
                  <span className="country-label label">Country:</span>

                  <span> </span>

                  <span className="country-data">
                    {selectedUser.address.country}
                  </span>
                </div>

                <div className="personal-details">
                  <span className="state-label label">State:</span>

                  <span> </span>

                  <span className="state-data">
                    {selectedUser.address.state}
                  </span>
                </div>

                <div className="personal-details">
                  <span className="street-label label">Street Address:</span>

                  <span> </span>

                  <span className="street-data">
                    {selectedUser.address.streetAddress}
                  </span>
                </div>

                <div className="personal-details">
                  <span className="zip-label label">ZIP:</span>

                  <span> </span>

                  <span className="zip-data">
                    {selectedUser.address.zipCode}
                  </span>
                </div>
              </div>
            </fieldset>
          </div>
        </div>
      )}

      <div className="friends-list">
        {userFriends ? (
          userFriends.map((friend, index) => (
            <Link key={friend.id} to={`/user/${friend.id}`}>
              <User
                name={friend.name}
                lastName={friend.lastName}
                prefix={friend.prefix}
                title={friend.title}
                img={`${friend.imageUrl}/${friend.id}`}
              />
            </Link>
          ))
        ) : (
          <div> Loading... </div>
        )}

        {friendsLoading ? <h1>Loaidng...</h1> : ""}
      </div>
    </div>
  );
};

export default UserDetails;
Ali H. Kudeir
  • 756
  • 2
  • 9
  • 19
  • Thank you so much! It worked! could you please view my last question if you have time? No one was able to help me with that: https://stackoverflow.com/questions/70378225/how-should-i-stop-react-from-re-rendering-component-after-i-change-the-route-and – nick1212 Dec 16 '21 at 15:42
  • Hey, glad it worked. Can you please mark it as the answer? I will also check your other question. – Ali H. Kudeir Dec 16 '21 at 15:44
  • I think now it's marked right? I am new to this platform, sorry do know know much of it – nick1212 Dec 16 '21 at 16:11
  • Yes, welcome here. – Ali H. Kudeir Dec 16 '21 at 16:12