我有一个应用程序,有两个标签"苹果"和"香蕉".每个选项卡都有一个用useState实现的计数器.

const Tab = ({ name, children = [] }) => {
  const id = uuid();
  const [ count, setCount ] = useState(0);

  const onClick = e => {
    e.preventDefault();
    setCount(c => c + 1);
  };

  const style = {
    background: "cyan",
    margin: "1em",
  };

  return (
    <section style={style}>
      <h2>{name} Tab</h2>
      <p>Render ID: {id}</p>
      <p>Counter: {count}</p>
      <button onClick={onClick}>+1</button>
      {children}
    </section>
  );
};

令人困惑的是,计数器状态在两个选项卡之间共享!

如果我在一个选项卡上增加计数器,然后切换到另一个选项卡,计数器也会在那里更改.

这是为什么?


以下是我的完整应用程序:

import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { v4 as uuid } from "uuid";
import { HashRouter as Router, Switch, Route, Link } from "react-router-dom";

const Tab = ({ name, children = [] }) => {
  const id = uuid();
  const [ count, setCount ] = useState(0);

  const onClick = e => {
    e.preventDefault();
    setCount(c => c + 1);
  };

  const style = {
    background: "cyan",
    margin: "1em",
  };

  return (
    <section style={style}>
      <h2>{name} Tab</h2>
      <p>Render ID: {id}</p>
      <p>Counter: {count}</p>
      <button onClick={onClick}>+1</button>
      {children}
    </section>
  );
};

const App = () => {
  const id = uuid();

  return (
    <Router>
      <h1>Hello world</h1>
      <p>Render ID: {id}</p>
      <ul>
        <li>
          <Link to="/apple">Apple</Link>
        </li>
        <li>
          <Link to="/banana">Banana</Link>
        </li>
      </ul>
      <Switch>
        <Route
          path="/apple"
          exact={true}
          render={() => {
            return <Tab name="Apple" />;
          }}
        />
        <Route
          path="/banana"
          exact={true}
          render={() => {
            return <Tab name="Banana" />;
          }}
        />
      </Switch>
    </Router>
  );
};

const container = document.getElementById("root");
const root = createRoot(container);

root.render(<App />);

版本:

  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router": "5.2.1",
    "react-router-dom": "5.2.1",
    "uuid": "^9.0.0"
  },

推荐答案

这与Switch works in react-router-dom的方式有关

最终,您的组件树保持不变,即使您切换了路由.

它始终是路由->交换机-&>路由-&>选项卡

由于Switch的工作方式,Reaction从不"挂载"新组件,它只是重用旧树,因为它可以.

我以前遇到过这个问题,解决方法是在某个地方添加一个密钥,比如在TabRoute上.我通常把它加到Route中,因为在我看来,它更有意义:

      <Switch>
        <Route
          key={'apple'}
          path="/apple"
          exact={true}
          render={() => {
            return <Tab name="Apple" />;
          }}
        />
        <Route
          key={'banana'}
          path="/banana"
          exact={true}
          render={() => {
            return <Tab name="Banana" />;
          }}
        />
      </Switch>

判断这个堆栈闪电战:

https://stackblitz.com/edit/react-gj5mcv?file=src/App.js

当然,当每个选项卡卸载时,您的状态将在每个选项卡中重置,这可能是也可能不是所需的.当然,解决这个问题的办法(如果这对你来说是个问题)是,一如既往地提升国家地位.

Javascript相关问答推荐

为什么有些库公开了执行相同任务的方法,但每个方法都处于同步/同步上下文中?

Angular:ng-contract未显示

在JavaScript中,是否有一种方法可以创建自定义thable,在等待某些代码后自动触发它?

序列查找器功能应用默认值而不是读取响应

React:未调用useState变量在调试器的事件处理程序中不可用

微软Edge Select 间隙鼠标退出问题

jQuery s data()[storage object]在vanilla JavaScript中?'

更改JSON中使用AJAX返回的图像的路径

使用LocaleCompare()进行排序时,首先使用大写字母

在WordPress中使用带有WPCode的Java代码片段时出现意外令牌错误

从Nextjs中的 Select 项收集值,但当单击以处理时,未发生任何情况

如何限制显示在分页中的可见页面的数量

为列表中的项目设置动画

无法检索与Puppeteer的蒸汽游戏的Bundle 包价格

将相关数据组合到两个不同的数组中

用另一个带有类名的div包装元素

如何在尚未创建的鼠标悬停事件上访问和着色div?

在HTML5画布上下文中使用putImageData时,重载解析失败

如何正确地在ComponentWillUnmount中卸载状态以避免内存泄漏?

将Windows XP转换为原始数据以在html前端中显示