【问题标题】:react router unmount function component反应路由器卸载功能组件
【发布时间】:2019-10-02 15:22:40
【问题描述】:

我正在使用 React Router 并且有两条路由渲染相同的组件:

<Switch>
    <Route path="/aaa" component={Cmp} />
    <Route path="/bbb" component={Cmp} />
</Switch>

这是 Cmp 实现:

class Cmp extends Component {
    componentWillUnmount() {
        console.log('******************* UNMOUNTED');
    }

    render() {
        return null;
    }
}

正如我所料,在 /aaa/bbb 之间导航不会卸载 Cmp。

我正在转向钩子,所以我重写了组件:

function Cmp() {
    useEffect(() => {
        return () => {
            console.log('******************* UNMOUNTED');
        };
    });

    return null;
}

非常令人惊讶的是,在运行应用程序时,在 /aaa/bbb console.log 之间导航 Cmp 已卸载。
知道如何使用函数组件和钩子来防止不必要的卸载吗?

【问题讨论】:

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


【解决方案1】:

如果你想运行一个效果并且只清理一次(在挂载和卸载时),你可以传递一个空数组([])作为第二个参数。这告诉 React 你的效果不依赖于任何来自 props 或 state 的值,所以它永远不需要重新运行。这不是作为特殊情况处理的——它直接遵循依赖数组的工作方式。 ...read more

现在,每次重新渲染 Cmp 组件时都会调用您的效果。如果您只想在卸载时调用效果,则必须将带有空数组的第二个参数传递给 useEffect

useEffect(() => {
    return () => {
        console.log('******************* UNMOUNTED');
    };
}, []);

【讨论】:

    【解决方案2】:

    这是人们使用useEffect hook 时面临的一个非常普遍的问题。

    useEffect 每次重新渲染组件时都会调用钩子。 hook 的第二个参数需要一个依赖数组,因此只有在依赖项发生变化时才会调用 hook。如果你给它提供空数组,钩子只会在挂载时运行,返回的函数会在卸载之前被调用。

    提示:将此 ESLint 插件添加到您的项目中,以查找与钩子相关的问题。 https://www.npmjs.com/package/eslint-plugin-react-hooks

    import React, { useEffect } from 'react';
    import ReactDOM from 'react-dom';
    import { BrowserRouter, Route, Switch, Link } from 'react-router-dom';
    
    import './styles.css';
    
    const DemoComponent = () => {
      useEffect(() => {
        return () => {
          console.log('******************* UNMOUNTED');
        };
      }, []);
      return <div>Demo Component</div>;
    };
    
    const HomeComponent = () => {
      return <div>Home Component</div>;
    };
    
    function App() {
      return (
        <BrowserRouter>
          <div>
            <Link to="/">To Home</Link>
            <br />
            <Link to="/aaa">To AAA</Link>
            <br />
            <Link to="/bbb">To BBB</Link>
          </div>
          <Switch>
            <Route path="/(aaa|bbb)" component={DemoComponent} />
            <Route path="/" component={HomeComponent} />
          </Switch>
        </BrowserRouter>
      );
    }
    
    const rootElement = document.getElementById('root');
    ReactDOM.render(<App />, rootElement);  
    

    这是工作示例:https://codesandbox.io/s/9l393o7mlr

    【讨论】:

      【解决方案3】:

      结合 componentDidMount 和 componentWillUnmount

      这意味着您可以在同一个 useEffect 函数调用中使用 componentDidMount 和 componentWillUnmount。显着减少管理这两个生命周期事件所需的代码量。这意味着您可以轻松地在功能组件中使用 componentDidMount 和 componentWillUnmount。像这样: 更多更新请React: UseEffect

      import React, { useEffect } from 'react';
          const ComponentExample => () => {
              useEffect(() => {
                  // Anything in here is fired on component mount.
                  return () => {
                      // Anything in here is fired on component unmount.
                  }
              }, [])
          }
      

      【讨论】:

        猜你喜欢
        • 2021-03-13
        • 1970-01-01
        • 1970-01-01
        • 2015-10-10
        • 2019-06-14
        • 1970-01-01
        • 2021-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多