【问题标题】:React Router V4 - Initial State on Route ChangeReact Router V4 - 路由更改的初始状态
【发布时间】:2019-01-22 19:27:36
【问题描述】:

了解 React Router 我注意到当从路由 a 切换到 b 时,组件会回到其初始状态。

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

我如何实现一种方法,让单击同一路由 <NavLink/> 组件恢复到其原始状态 - 应该/可以在 React Router 的 onChange 钩子上完成吗?

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

下面是问题的抽象:

单击 Cat <p/> 标记应将其颜色更改为 green,单击同一路线 <NavLink to="/cat-view">cat</NavLink> 应将 cat 颜色状态恢复为其初始状态。即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

【问题讨论】:

    标签: javascript reactjs react-router react-router-v4


    【解决方案1】:

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

    如果您想在单击其NavLink 时更改状态,那么您需要明确地执行此操作。 有两种主要方法可以做到这一点:

    • 将状态提升到父级并在单击链接时显式更改它
    • 更改元素的键以强制重新安装
    • 为父级提供一种机制来接触子级并告诉它重置其状态

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

    Cat 演示了第一种方法。

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

    Dog 演示了第二种方法。

    这种方法在组件有很多自己的状态并且如果再次单击链接时希望全部重置的更复杂的场景中效果更好。

    Bunny 演示了第三种方法。

    这类似于 Dog 示例的 key 属性,但不会导致重新挂载。 Bunny 只是使用resetIndex 来使Bunny 自行重置。对此可能有几种技术方法。你只是想要一种方法来通知孩子重置自己。

    【讨论】:

    • @Jonca33 这在很大程度上取决于您的实际情况。如果您想要完全重置您的组件,那么重新挂载可能是合适的,但 实际上从 DOM 中删除元素(及其后代)并在其位置添加一个新元素。在某些情况下,这很好,而且比替代方案容易得多,而在其他情况下则不合适。
    • @Jonca33 您还需要小心使用这种方法,以避免在每次单击链接时意外导致它呈现两次——一次使用旧密钥,一次使用新密钥。
    • @Jonca33 我添加了第三种方法(Bunny),可以避免重新安装,但允许子级仍然控制重置(而不是需要将所有状态提升到父级)。跨度>
    • @RyanCogswell 我一直在关注这里的线程...仅供参考,当您将 resetRef 替换为 useEffect 时,Bunny 停止工作
    猜你喜欢
    • 2018-01-20
    • 2018-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-26
    • 2018-06-22
    • 1970-01-01
    • 2018-01-18
    相关资源
    最近更新 更多