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);
CodePudding user response:
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;