Maison  >  Questions et réponses  >  le corps du texte

Pourquoi useState est-il partagé entre les routes avec différents accessoires ?

J'ai une application avec deux onglets « Apple » et « Banane ». Chaque onglet dispose d'un compteur implémenté à l'aide de 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>
  );
};

Certainement, le statut du compteur est partagé entre les deux onglets !

Si j'incrémente le compteur sur un onglet puis que je passe à un autre onglet, le compteur change également.

Pourquoi est-ce ?


Voici mon application complète :

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 />);

Version :

  "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"
  },

P粉571233520P粉571233520225 Il y a quelques jours478

répondre à tous(2)je répondrai

  • P粉496886646

    P粉4968866462024-03-31 18:52:50

    Adam a une bonne explication et une bonne réponse sur ce qui se passe ici, c'est une optimisation qui ne supprime pas et ne réinstalle pas le même composant React simplement parce que le chemin de l'URL change. L'utilisation des clés React résoudra certainement ce problème, forçant React à remonter l'état Tab 组件,从而“重置”count.

    Je suggère d'utiliser une autre méthode lorsque name 属性从 "apple" 更改为 "banana" 时,保持挂载路由组件并简单地重置 count indique et vice versa.

    const Tab = ({ name, children = [] }) => {
      const id = uuid();
      const [count, setCount] = useState(0);
    
      useEffect(() => {
        setCount(0); // <-- reset to 0 when name prop updates
      }, [name, setCount]);
    
      const onClick = e => {
        e.preventDefault();
        setCount(c => c + 1);
      };
    
      const style = {
        background: "cyan",
        margin: "1em",
      };
    
      return (
        

    {name} Tab

    Render ID: {id}

    Counter: {count}

    {children}
    ); };

    Cela fera que l'optimisation RRD fonctionnera pour vous, pas contre vous.

    Si vous n'avez pas de name 这样的传递道具可以从中获取提示,则可以使用 location.pathnamej'aime

    . Notez que cela couple une certaine logique de composant interne avec des détails externes.

    Exemple : 🎜
    const { pathname } = useLocation();
    const [count, setCount] = useState(0);
    
    useEffect(() => {
      setCount(0);
    }, [pathname, setCount]);
    

    répondre
    0
  • P粉608647033

    P粉6086470332024-03-31 18:42:56

    Cela fonctionne avec Switch dans React-Router-Dom

    En fin de compte, votre arborescence de composants reste la même même si vous changez d'itinéraire.

    Toujours routeur -> Switch -> Routage -> Onglet

    En raison du fonctionnement de Switch, React n'installe jamais de nouveaux composants, il réutilise simplement l'ancienne arborescence parce qu'il le peut.

    J'ai déjà eu ce problème et la solution était d'ajouter une clé quelque part, par exemple dans TabRoute 上。我通常将其添加到 Route car cela a plus de sens à mon avis :

    
             {
                return ;
              }}
            />
             {
                return ;
              }}
            />
          

    Découvrez ce stack blitz :

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

    Bien entendu, votre état sera réinitialisé dans chaque onglet lorsque chaque onglet sera déchargé, ce qui peut être idéal ou non. Mais la solution à ce problème est bien sûr (si cela vous pose un problème), comme d’habitude, d’améliorer votre statut.

    répondre
    0
  • Annulerrépondre