petitviolet_blog

@petitviolet blog

react-routerで同じComponentにLinkで遷移したときにstateがリフレッシュされない

まとめ

Routeに異なるkeyを設定する

<Route exact key={'new'} path={'/posts/new'} component={EditPostComponent} />
<Route exact key={'edit'} path={'/posts/:id/edit'} component={EditPostComponent} />

<li>などでリストを表示したときにkeyを設定してないとwarningが表示されるが、それと同じことが起きていると思えばよい。 https://reactjs.org/docs/lists-and-keys.html#keys

サンプル

コードを貼り付けるとこんな感じ。

import * as React from 'react';
import {Link, Route, Router, Switch, useLocation} from 'react-router-dom';

const MyComponent = (props) => {
  const current = useLocation().pathname;
  const next = current == '/a' ? '/b' : '/a';
  const [counter, setCounter] = React.useState<number>(0);
  return (
    <>
      <div>
        <div>Counter: {counter}</div>
        <button onClick={() => setCounter(counter + 1)}>Increment</button>
      </div>
      <Link to={next}>Current: {current}, Next: {next}</Link>
    </>
  );
};

const App: React.FC = () => {
  const history = require('history').createBrowserHistory;
  // 同じMyComponentを表示する異なるパスがある
  return (
    <Router history={history()}>
      <Switch>
        <Route exact path={'/'} render={() => <Link to={'/a'}>To /a</Link>} />     
        <Route exact path={'/a'} component={MyComponent} />
        <Route exact path={'/b'} component={MyComponent} />
      </Switch>
    </Router>
  );
};

動かしてみると、パスが変わってもstateが保持されてしまっているのがわかる。 CodePenのとはimportしてたりわずかに違うが、コードとしては同じ。

See the Pen React Router missing key by petitviolet (@petitviolet) on CodePen.

先程のコードのRoutekeyを追加してみる。

-       <Route exact path={'/a'} component={MyComponent} />
-       <Route exact path={'/b'} component={MyComponent} />
+       <Route exact key={'a'} path={'/a'} component={MyComponent} />
+       <Route exact key={'b'} path={'/b'} component={MyComponent} />

動かしてみると、期待しているように動いているのがわかる。

See the Pen React Router missing key by petitviolet (@petitviolet) on CodePen.