导航时如何防止导航栏菜单重新呈现?反应路由器 v4

How to prevent NavBar Menu to re render when navigating? React Router v4

我正在从 API 服务器获取数据以动态生成 NavBar 菜单。

问题是每次我浏览页面时菜单都会重新呈现。 无法弄清楚为什么会这样。我尝试了 react-router v4 的不同示例,例如使用,但菜单总是重新呈现。

在动态生成菜单时,您使用什么模式来防止 NavBar 菜单重新呈现?

基本设置文件如下:

Main.js 文件:

import React from 'react'
import { Route } from 'react-router-dom'
import Home2 from './Home'
import Head from './Head'
import Rules from './Rules'

const Main = () => (
  <main>
    <Route  path='/' component={Head}/>
    <Route exact path='/' component={Home}/>
    <Route exact path='/rules' component={Rules}/>
  </main>
)

export default Main

Head.js 文件:

import React, { Component } from 'react'
import Menu from 'semantic-ui-react'

class Head extends Component {
  constructor(props) {
   super(props);
  }

  getInitialData() {
    //fetch data from server
  }

  componentWillMount() {
    this.getInitialData();
  }

  render() {
    return (
      <header>
        <nav>
          <Menu>
            {/* fetched data */}
        </nav>
      </header>
    )
  }
}

export default Head

Index.js 文件:

import React from 'react'
import { render } from 'react-dom'
import Main from './components/Main'
import { BrowserRouter } from 'react-router-dom'

render((
  <BrowserRouter>
    <Main />
  </BrowserRouter>
), document.getElementById('root'));

使用 React Router v3 这段代码工作正常:

var Routes = (
  <Router>
    <Route path="/" component={Head}>
      <IndexRoute component={Home} />
    </Route>
  </Router>
);

但是在 v4 中我不能嵌套路由。

因为您将 header 作为路线包括在内,每次路线更改时都是 re-rendering。只需将 header 拉出路线,当 route-based 组件发生变化时它将保持一致:

import React from 'react'
import { Route, Switch } from 'react-router-dom'
import Home2 from './Home'
import Head from './Head'

const Main = () => (
  <main>
    <Head />
    <Switch>
      <Route exact path='/' component={Home}/>
      // Add any other routes you want here
    </Switch>
  </main>
)

export default Main;

我也遇到过类似的问题,最后还是没能解决,所以试试下面的方法。 在我的主要路线的更新中,请求菜单,如果我没有创建它。

    #Route.js

    state = {
        menu: null
    };

    componentDidUpdate() {
            if ( !this.state.menu ) {
                this._instanceMenu();
            }
    } 

    render() {
            return (
                    <React.Fragment>
                            { this._renderStaticContent() }
                            <Switch>
                                    <Route exact path={ '/' } component={ DefaultPage } />
                                    <Route component={ Error404 } />
                            </Switch>
                    </React.Fragment>
            );
    };

第一次fetch请求,然后存到localstorage,后面如果已经在localStorage,我就不return去fetch了。

    #Route.js

    _instanceMenu() {
            if ( !this.helper.getMenu() ) {
                    this.helper.instanceMenu( ( menu ) => {
                            this.setState( { menu } );
                    } );
            }

            this.setState( { menu: this.helper.getMenu() } );
    }

可选

    #Helper.js

    instanceMenu = ( callback ) => {
            axios.get(
                    this._urlMenu,
            ).then( ( response ) => {
                    localStorage.setItem( this._menu, JSON.stringify( response.data ) );
                    callback( this.getMenu() );
            } ).catch( ( error ) => {
                    console.log( error );
            } );
    };

    getMenu = () => {
            return JSON.parse( localStorage.getItem( this._menu ) );
    };

最后我用高阶组件将它发送到我的组件 (Readme)

     #Route.js

     _renderStaticContent = () => {
            if ( !this.authService.isLoggedIn() ) return null;

            return <React.Fragment>
                    <Route component={ HeaderContainer } />
                    <Route component={ wrap( SidebarContainer, { 'menu': this.state.menu } ) } />
                    <Route component={ Footer } />
            </React.Fragment>;
    };

PD:对不起我的英语。

我也遇到了同样的问题,但这与路由中的 header 无关。事实上,这是一些不太明显的东西,很难确定。

我们从自定义挂钩中获取一些信息,但是这个自定义挂钩从状态返回整个 object 而不是解构特定字段。因此,object 中的其他字段(我们不感兴趣)在路由更改时更新,因此这触发了 header.[=14= 中不必要的 re-render ]

只是举个例子;

What we WERE doing (incorrect)

const { auth } = useSelector(state => state); 

What we changed it to

const { user } = useSelector(state => state.auth);

auth 中的其他字段正在更改,但我们对这些不感兴趣。通过仅对用户进行解构,其他字段将被忽略并且 re-render 停止。

我意识到这可能是一个非常独特的场景,但希望它能对某人有所帮助。

虽然已经晚了,但我想我会 post 在这里为可能正在为此苦苦挣扎的其他人提供答案。

首先,根据@JulesDupont 的回答,您的 <Head /> 组件应该在您的路线之外。

const App = () => (
  <>
    <Head />
    <Switch>
      <Route exact path='/' component={Component 1}/>
      // Add any other routes goes here
    </Switch>
  </>
)

export default App;

此外,您要搜索的模式是使用 react-router-dom 中的 <Link> 标签。如果您可以在此处 post 您的 Head 组件,那就太好了。您很有可能在 <Menu />.

中使用 <a href='/#'> 标签而不是 <Link to='/#'> 标签进行重定向

<a> 标签会触发整个页面重新加载,导致您的 <Head /> 组件在您每次导航到新页面时重新加载,从而重新获取所有数据。但是,<Link> 标记不会触发整页重新加载。

示例:

import { Link } from 'react-router-dom';

const Head = () => {
    return (
        <ul>
            <Link to='/your-route'>Item 1 (fetches data)<Link>
            <Link to='/your-other-route'>Item 2 (fetches data)</Link>
        </ul>
    )
}

export default Head;

这将确保您的 Head 组件在导航到另一条路线时不会重新呈现或重新获取数据。