Реакция маршрутизатора Ссылка не вызывает повторную визуализацию при посещении по тому же пути

Я использую реагирующий маршрутизатор v4, возникла проблема с перезагрузкой страницы (не window.location.reload). Я лучше приведу реальный вариант использования, чтобы объяснить проблему, мы используем приложение социальной сети в качестве примера:

  1. Пользователь A прокомментировал сообщение пользователя B, на странице пользователя B появится уведомление.
  2. пользователь B нажал на уведомление, мы делаем this.props.history.push('/job/' + id'), это сработало, следовательно, пользователь B перешел на страницу job/123.
  3. Пользователь A прокомментировал снова, новое уведомление появляется на странице пользователя B, в то время как пользователь B все еще остается на странице job/123, он щелкнул ссылку уведомления и запустил this.props.history.push('/job' + id'). Но он не увидит повторную визуализацию страницы, он НЕ видел последний комментарий, потому что страница ничего не делает.

это хорошее объяснение, но было бы лучше увидеть ваш код, имеющий отношение к этой проблеме, иначе вам было бы очень трудно помочь.

Andrew Lohr 30.08.2018 16:35

@AndrewLohr мне сложно реплицировать, поскольку я использую websocket, уведомление в реальном времени было отправлено от пользователя A к пользователю B, поэтому есть вероятность, что пользователь B щелкнет новое уведомление по тому же пути.

Hoknimo 30.08.2018 16:48

Я думаю, ваша проблема заключается в том, что вы нажимаете слишком один и тот же маршрут, и ваш компонент не обновляется после нажатия. postId не отличается от страниц /notification? postId - 123 на обеих страницах?

Soroush Chehresa 30.08.2018 16:50

@soroushchehresa Я думаю, что использование /notification/postId сбивает людей с толку, я изменил его на задание, каждая деталь задания имеет комментарий, уведомление предназначено только для того, чтобы сообщить пользователю, что на указанной странице вакансии появилось новое уведомление.

Hoknimo 30.08.2018 16:52
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
4
18 957
4

Ответы 4

Вы должны посмотреть обновление postId в жизненном цикле componentWillUpdate и сделать что-нибудь отсюда вроде этого:

  componentWillUpdate(np) {
    const { match } = this.props;
    const prevPostId = match.params.postId;
    const nextPostId = np.match.params.postId;
    if (nextPostId && prevPostId !== nextPostId){
      // do something
    }
  }

componentWillUpdate - это не «здоровый» метод жизненного цикла, я полагаю? Он устарел в React 16. Кстати, postId всегда будет таким же, потому что многие уведомления указывают на один и тот же пост.

Hoknimo 30.08.2018 17:02

Правильно, вместо этого вы должны выполнить аналогичную проверку в componentDidUpdate (). Этот ответ может быть полезным.

FranCarstens 30.08.2018 17:05

но как здесь работает логика? nextPostId и prevPostId всегда будут одинаковыми

Hoknimo 30.08.2018 17:09

@Hoknimo При использовании componentWillUpdate с условиями это может быть здоровым методом жизненного цикла!

Soroush Chehresa 30.08.2018 22:27

@Hoknimo При нажатии на / уведомление с новым postId на странице уведомления nextPostId будет обновлен до нового postId с URL-адреса.

Soroush Chehresa 30.08.2018 22:37

@Hoknimo Например: от / notification / 123 до / notification / 456

Soroush Chehresa 30.08.2018 22:40

Вы описываете 2 различных типа изменений состояния.

В первом сценарии, когда пользователь B является нет на странице /job/:id и щелкает ссылку, вы получаете изменение URL-адреса, которое запускает изменение состояния в маршрутизаторе и распространяет это изменение на ваш компонент, чтобы вы могли видеть комментарий.

Во втором сценарии, когда пользователь B является уже в, страница /job/:id и приходит новый комментарий, URL-адрес не нужно менять, поэтому нажатие на ссылку не изменит URL-адрес и не вызовет изменение состояния в маршрутизатор, поэтому вы не увидите новый контент.

Я бы, наверное, попробовал что-то вроде этого (псевдокод, потому что я не знаю, как вы получаете новые комментарии или подписываетесь через веб-сокет):

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";

class Home extends React.Component {
  render() {
    return (
      <div>
        <h1>The home page</h1>

        {/* This is the link that the user sees when someone makes a new comment */}
        <Link to = "/job/123">See the new comment!</Link>
      </div>
    );
  }
}

class Job extends React.Component {
  state = { comments: [] };

  fetchComments() {
    // Fetch the comments for this job from the server,
    // using the id from the URL.
    fetchTheComments(this.props.params.id, comments => {
      this.setState({ comments });
    });
  }

  componentDidMount() {
    // Fetch the comments once when we first mount.
    this.fetchComments();

    // Setup a listener (websocket) to listen for more comments. When
    // we get a notification, re-fetch the comments.
    listenForNotifications(() => {
      this.fetchComments();
    });
  }

  render() {
    return (
      <div>
        <h1>Job {this.props.params.id}</h1>
        <ul>
          {this.state.comments.map(comment => (
            <li key = {comment.id}>{comment.text}</li>
          ))}
        </ul>
      </div>
    );
  }
}

ReactDOM.render(
  <BrowserRouter>
    <Switch>
      <Route exact path = "/" component = {Home} />
      <Route path = "/job/:id" component = {Job} />
    </Switch>
  </BrowserRouter>,
  document.getElementById("app")
);

Теперь страница будет обновляться в обоих сценариях.

Во многих случаях это кажется обычным сценарием. С ней можно справиться, используя множество различных подходов. Отметьте это вопрос о переполнении стека. Есть несколько хороших ответов и выводов. Лично для меня этот подход имел больше смысла.

location.key изменяется каждый раз, когда пользователь пытается перемещаться между страницами, даже в пределах одного и того же route. Чтобы проверить это место ниже блока кода в вашем компоненте /jod/:id:

componentDidUpdate (prevProps) {
    if (prevProps.location.key !== this.props.location.key) {
      console.info("... prevProps.key", prevProps.location.key)
      console.info("... this.props.key", this.props.location.key)
    }
  }

У меня была точно такая же ситуация. Обновленное состояние в componentDidUpdate. После этого заработало как положено. Нажатие на элементы в пределах одного маршрута обновляет состояние и отображает правильную информацию.

Я предполагаю (поскольку не уверен, как вы передаете / обновляете комментарии в /job/:id), если вы установите что-то подобное в своем компоненте /job/:id, должно работать:

componentDidUpdate (prevProps) {
    if (prevProps.location.key !== this.props.location.key) {

      this.setState({
        comments: (((this.props || {}).location || {}).comments || {})
      })
    }
  }

это решило проблему для меня:

import { BrowserRouter as Router,Route,Switch,Redirect} from "react-router-dom";

<Router>  
 <Switch>

     <Redirect from = "/x_walls/:user_Id" to='/walls/:user_Id'/>
     <Route path = "/walls/:user_Id" exact render = {(props) => <Wall {...props}/> }/>           

  </Switch>

</Router>

и когда вы хотите назвать "стены", вы просто вызываете "x_walls" вместо этого

Другие вопросы по теме