React Router V4 - 路由更改的初始状态

React Router V4 - Initial State on Route Change

学习 React Router 我注意到当从路由 a 切换到 b.

时,组件会回到其初始状态

为什么在同一条路线上再次点击时不会发生同样的情况,即 a 到 a

我如何实现一种方法,点击相同的路由 <NavLink/> 组件恢复到其原始状态 - Should/Could 在 React Router 的 onChange 挂钩上完成?

如果这是一个反模式,请告诉我我还能如何完成以下任务:我需要我的组件恢复到其原始状态,不仅在切换路由时,而且在 用户选择再次点击同一路线。

下面是问题的抽象:

单击猫 <p/> 标签应将其颜色更改为 green,单击同一路线 <NavLink to="/cat-view">cat</NavLink> 应将猫颜色状态恢复为初始状态。即 color: false

就像从路线 a 切换到 b 时一样(在我的例子中是猫到狗)

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

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

  function ChangeColor() {
    setColor(true);
  }

  console.log(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.log("cat route changed")}
            />
            <Route
              path="/dog-view"
              render={() => <Dog/>}
              onChange={console.log("dog route changed")}
            />
          </Switch>
        </div>
      </Router>
    );
  }
}

export default withRouter(PetShop);

这里是 code sandbox

由于您使用的 react-router Switch 组件仅呈现第一个匹配项,因此当您从路线 a 切换到 b, a 正在卸载;这会抛出它的所有状态,所以如果你切换回 a 你有一个全新的组件,它获取你为其状态指定的初始值(例如 false for Cat color)。单击不会更改呈现的 RouteNavLink 会保留相同的元素,并且不会影响其状态。

如果你想在点击 NavLink 时改变状态,那么你需要明确地这样做。 您可以通过两种主要方式执行此操作:

  • 将状态提升到 parent 并在单击 link
  • 时明确更改它
  • 更改元素的键以强制重新挂载
  • 为 parent 提供一种机制以进入 child 并告诉它重置其状态

这是您的沙箱的修改版本,演示了所有这些:

Cat 演示了第一种方法。

我已将状态从 Cat 移动到 PetShop(Cat 现在只使用道具)。我还在 cat 的 NavLink 中添加了一个 onClick,将状态设置回 false

Dog 演示了第二种方法。

这种方法在更复杂的情况下效果更好,在这种情况下,组件有很多自己的状态,如果您再次单击 link,您希望它全部重置。

Bunny 演示了第三种方法。

这类似于 Dog 示例的密钥 属性,但不会导致重新挂载。 Bunny 只是在效果中使用 resetIndex 导致 Bunny 自行重置。为此可能有几种技术方法。您只需要一种方法来通知 child 自行重置。