React Router V4 — исходное состояние при изменении маршрута

Узнав о React Router, я заметил, что компонент возвращается в исходное состояние при переключении с маршрута от а до б.

Почему этого не происходит при повторном нажатии на тот же маршрут, т.е. а к а?

Как я могу реализовать способ, при котором при нажатии на тот же маршрут <NavLink/> компонент возвращается в исходное состояние - следует ли/можно ли это сделать на крючке onChange React Router?

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

Ниже абстракция проблемы:

Щелчок по тегу Cat <p/> должен изменить его цвет на green, щелчок по тому же маршруту <NavLink to = "/cat-view">cat</NavLink> должен вернуть состояние цвета кошки обратно в исходное состояние. то есть color: false

Так же, как и при переключении с маршрута от а до б (в моем случае кошка на собаку)

// Cat Component
import React, { useState } from "react";

export const Cat = () => {
  const [color, setColor] = useState(false);

  function ChangeColor() {
    setColor(true);
  }

  console.info(color)

  return (
    <p onClick = {ChangeColor}>
      Click on this <span className = {color ? "green" : " "}>Cat</span>
    </p>
  );
};

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

// Main Component
class PetShop extends Component {
  state = {};

  render() {
    return (
      <Router history = {browserHistory}>
        <div>
          <ul>
            <li>
              <NavLink to = "/">home</NavLink>
            </li>
            <li>
              <NavLink to = "/cat-view">cat</NavLink>
            </li>
            <li>
              <NavLink to = "/dog-view">dog</NavLink>
            </li>
          </ul>

          <Switch>
            <Route
              path = "/cat-view"
              render = {() => <Cat/>}
              onChange = {console.info("cat route changed")}
            />
            <Route
              path = "/dog-view"
              render = {() => <Dog/>}
              onChange = {console.info("dog route changed")}
            />
          </Switch>
        </div>
      </Router>
    );
  }
}

export default withRouter(PetShop);

вот песочница кода

Поведение ключевого слова "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) для оценки ваших знаний,...
4
0
3 124
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку вы используете компонент react-router Switch, который отображает только первое совпадение, при переключении с Route а на ба размонтируется; это отбрасывает все его состояние, поэтому, если вы переключитесь обратно на а, у вас будет совершенно новый компонент, который получает начальное значение, указанное вами для его состояния (например, false для Catcolor). Щелчок по NavLink, который не меняет отображаемый Route, оставляет тот же элемент на месте и не влияет на его состояние.

Если вы хотите изменить состояние при нажатии на его NavLink, то вам нужно сделать это явно. Есть два основных способа сделать это:

  • поднимите состояние до родителя и явно измените его по щелчку ссылки
  • измените ключ элемента, чтобы принудительно перемонтировать
  • обеспечить механизм для родителя, чтобы добраться до ребенка и сказать ему сбросить свое состояние

Вот модифицированная версия вашей песочницы, которая демонстрирует все это:

Edit  react-remount-route

Cat демонстрирует первый подход.

Я переместил состояние с Cat на PetShop (Cat теперь использует только props). Я также добавил onClick в NavLink для кота, который возвращает состояние false.

Dog демонстрирует второй подход.

Этот подход будет лучше работать в более сложном сценарии, когда компонент имеет много собственных состояний, и вы хотите, чтобы все они были сброшены, если вы снова нажмете на ссылку.

Bunny демонстрирует третий подход.

Это похоже на ключевое свойство для примера с собакой, но не вызывает повторного монтирования. Bunny просто использует resetIndex, чтобы заставить Bunny сбросить себя. Вероятно, для этого существует несколько технических подходов. Вам просто нужен способ сигнализировать ребенку, чтобы он перезагрузил себя.

Большое спасибо, Райан! Насколько вам известно, я прошу антипаттерн для «Святого Грааля» React, а также не ухудшит ли реализация key, как вы описали в компоненте Dog, производительность и оптимизацию React?

Jonca33 22.01.2019 21:16

@ Jonca33 Jonca33 Во многом это зависит от вашего реального сценария. Если вам нужен полный сброс вашего компонента, то перемонтирование может быть уместным, но этот будет фактически удаляет элемент (и его потомков) из DOM и добавляет новый элемент на его место. В некоторых сценариях это нормально и намного проще, чем альтернативы, и в других случаях, когда это было бы неуместно.

Ryan Cogswell 22.01.2019 21:28

@ Jonca33 Jonca33 Вы также должны быть осторожны с этим подходом, чтобы случайно не вызвать его рендеринг дважды каждый раз, когда вы нажимаете ссылку - один раз со старым ключом и один раз с новым ключом.

Ryan Cogswell 22.01.2019 21:32

В этом есть смысл. Моя настоящая проблема (которую я решил не показывать здесь, потому что это было бы слишком многословным кодом) — это компонент child, который получает несколько изменений пользовательского интерфейса на основе взаимодействия с пользователем. Основываясь на вашем объяснении, правильно ли я предполагаю, что было бы лучше сделать то, что вы сделали с dog, и поднять состояние, чтобы исправить ситуацию?

Jonca33 22.01.2019 21:32

@ Jonca33 Jonca33 Я добавил третий подход (Bunny), который позволяет избежать повторного монтирования, но позволяет дочернему элементу по-прежнему контролировать сброс (вместо того, чтобы поднимать все состояние до родительского).

Ryan Cogswell 22.01.2019 21:49
props.resetRef.current... каждый день узнаешь что-то новое! Где я могу прочитать больше о таком подходе? Спасибо!
Jonca33 22.01.2019 22:03

@ Jonca33 Jonca33 Я добавил альтернативный подход для примера Bunny.

Ryan Cogswell 22.01.2019 22:12

@RyanCogswell, спасибо, я тоже искал такое решение. мир!

Null isTrue 22.01.2019 22:12

@RyanCogswell Я следил за этой веткой здесь ... К вашему сведению, Bunny перестал работать, когда вы заменили resetRef на useEffect.

Null isTrue 22.01.2019 22:19

@NullisTrue Спасибо - у меня возникла проблема с синтаксисом при вызове useEffect. Я не заключал props.resetIndex в массив.

Ryan Cogswell 22.01.2019 22:27

@ Jonca33 Jonca33 Я думаю, что подход ref проблематичен, поэтому я удалил его. В определенных сценариях это могло привести к обновлению состояния несмонтированного компонента.

Ryan Cogswell 22.01.2019 22:29

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