#javascript #reactjs
Вопрос:
Приведенный ниже код выполняется, например, при переходе с одной страницы на другую. когда я нажимаю на продукт из списка страниц категории, приведенный ниже код устанавливает ключ хранения сеанса, который будет содержать позицию страницы категории (сколько страниц было прокручено).
Поэтому, когда откроется страница продукта, он сохранит свой ключ в сеансе, и если он снова посетит ту же страницу категории, он восстановит положение страницы.
Я пытаюсь заставить этот код сохранить только один ключ сеанса и удалить ранее сохраненный ключ сеанса независимо от того, на какую страницу пользователь нажимает на веб-сайте (т. е. страницу категории, страницу продукта).
CategoryPage.js
const [scrollPosition, setScrollPosition] = React.useState('');
React.useEffect(() => {
var pathName = document.location.pathname.substr(1);
if (window) {
window.onscroll = function (e) {
setScrollPosition(window.scrollY);
if(scrollPosition != 0){
sessionStorage.setItem("scrollPosition_" pathName, scrollPosition);
}
};
}
}, [scrollPosition]);
React.useEffect(() => {
var pathName = document.location.pathname.substr(1);
if (window amp;amp; sessionStorage.getItem("scrollPosition_" pathName)) {
$(window).scrollTop(sessionStorage.getItem('scrollPosition_' pathName));
console.log('position_set to = ' sessionStorage.getItem('scrollPosition_' pathName));
}
}, []);
есть какие-нибудь мысли по этому поводу, чтобы удалить предыдущий сессионный ключ?
Ответ №1:
Если вы используете redux с react, вы действительно можете создать редуктор, который отслеживает местоположение, отправляя действия, содержащие информацию о том, был ли пользователь на странице продукта.
Что-то вроде этого:
Так что, если у вас есть несколько маршрутов, таких как:
/category/house/3213124(product_id)
/category/garden/dsfsdfs(product_id)
В вашем маршрутизаторе вы можете адресовать их следующим образом:
/category/house/{id}
/category/garden/{id}
Тогда вы можете использовать :
let { id } = useParams();
if(id !== undefined || ""){
dispatch(userIsOnProductPageAction(true))
}
Когда пользователи нажимают кнопку «Назад» с помощью селектора для редуктора, у вас есть информация о том, кто был пользователем на странице продукта… если true, выполните код, если false, ничего не делайте.
Также после выполнения кода вы отправляете userIsOnProductPageAction(false)
.
Если вы не используете redux, вы можете применить ту же логику, но проблема в том, что вам нужно сохранить состояние wasUserOnPage
и каким-то образом получить к нему доступ, когда вы находитесь на странице категории.
Поскольку я не знаю, как выглядит ваше приложение React, я не могу сказать вам, как этого добиться. Если продукт является дочерним элементом, а категория является родительским элементом, нажав кнопку «Назад», вы, вероятно, могли бы отправить эту информацию через реквизит.
ИЗМЕНИТЬ: это должно выглядеть примерно так
class main extends React.Component {
constructor(props) {
super(props)
this.handler = this.handler.bind(this)
}
handler() {
this.setState({
wasOnProductPage:false
})
}
render() {
return <Category handler = {this.handler} props={this.props.wasOnProductPage} />
<Product handler = {this.handler} />
}
}
class Category extends React.Component {
render() {
if(props){
do code for viewport
then acitave this.props.handler and set it to false
}
}
}
class Product extends React.Component {
render() {
return <BackButton onClick = {this.props.handler(true)}/ >
}
}
Комментарии:
1. Большое спасибо за ответ, приложение React не использует redux, также продукт не является дочерним элементом, а категория не является родительским элементом. Возможно, мы сможем наблюдать нажатие кнопки «Назад» с помощью router.beforePopState, но я новичок в реагировании, поэтому не очень хорошо знаю, как ее использовать, и установить информацию на странице продукта, и если нажать кнопку «назад», проверьте, отображается ли страница категории/пришла со страницы продукта.
2. Если компонент приложения(основной компонент) находится в состоянии ожидания, а компонент продукта является дочерним элементом компонента приложения(так и должно быть), пожалуйста, прочитайте это: pluralsight.com/guides/… — Передача реквизита от Ребенка к Родителю. Что вам нужно сделать, так это при нажатии кнопки «Назад» вы отправляете реквизиты в компонент приложения, а там удерживаете страницу состояния wasUserOnProduct и меняете ее с false на true. Тогда у вас есть эта информация, когда вы находитесь в компоненте категории
3. Спасибо за предложение, я посмотрю на него, если возможно передать данные со страницы продукта на страницу категории.
4. Просто для ясности. Вы удерживаете состояние в основном компоненте. Вы меняете состояние из компонента продукта в основной компонент. Вы отправляете состояние из основного компонента в компонент категории, после прочтения его в компоненте категории и выполнения кода вы снова меняете состояние в основном компоненте из компонента категории
5. <>Вы меняете состояние компонента продукта в главном компоненте. <> когда это будет сделано ? когда нажимается кнопка «Назад» со страницы продукта ?
Ответ №2:
Что я понимаю, так это то, что при загрузке страницы вы хотите:
- Если эта страница была последней посещенной страницей: загрузите ее сохраненное местоположение.
- Еще: удалите последнее сохраненное местоположение и сохраните его при прокрутке.
Тогда, похоже, вам нужно сохранить какой-то идентификатор страницы с указанием местоположения, которое вы сохраняете/загружаете. Этот уникальный идентификатор явно может быть URL-адресом.
Затем вы можете использовать аналогичную версию своего кода:
const [scrollPosition, setScrollPosition] = React.useState('');
const getPathname = () => document.location.pathname.substr(1);
React.useEffect(() => {
if (window) {
window.onscroll = function (e) {
setScrollPosition(window.scrollY);
if (scrollPosition != 0) {
const savedPosition = { position: scrollPosition, pathName: getPathname() };
sessionStorage.setItem('scrollPosition', JSON.stringify(savedPosition));
}
};
}
}, [scrollPosition]);
React.useEffect(() => {
const lastSavedPosition = JSON.parse(sessionStorage.getItem('scrollPosition'));
if (window amp;amp; lastSavedPosition amp;amp; getPathname() === lastSavedPosition.pathName) {
$(window).scrollTop(lastSavedPosition.position);
console.log(`position_set to = ${lastSavedPosition.position}`);
}
}, []);
Комментарии:
1. Спасибо за ответ, да, я пытаюсь удалить предыдущий ключ сеанса и добавить новый ключ.
2. Ошибка ссылки: позиция не определена console.log(
position_set to = ${position}
);3. Да, моя вина, так и должно быть
lastSavedPosition.position
. Обновил свой ответ4. можем ли мы использовать setTimeout(()=>window.scrollTo(0, lastSavedPosition.position),10); вместо $(window).scrollTop(lastSavedPosition.position); ?
5. Конечно, логика, которую я предложил, должна была обрабатывать сохранение и загрузку местоположения относительно URL-адреса. Вы можете применить к этому любую логику, какую захотите 🙂