【问题标题】:Stop the re-rendering of Sidebar in Page using react-router-dom使用 react-router-dom 停止页面中侧边栏的重新渲染
【发布时间】:2020-07-19 22:54:55
【问题描述】:

任何帮助将不胜感激,所以我有一个带有页眉、侧边栏、页脚和主页面的页面,其中侧边栏有静态链接,单击时会显示组件。这里的问题是单击链接,侧边栏,页眉和页脚正在重新渲染,这不是必需的。我在侧边栏中尝试了 shouldComponentUpdate 但它不起作用。 项目使用的版本: “反应”:“^16.12.0”, “反应域”:“^16.12.0”, "react-router-dom": "^5.1.2", 我会一直在这里,直到这个问题得到解决,所以请随时提出任何问题

这里是 myApp.js(根文件)

function App() {
  return (
    <Provider store={Store}>
        <Router history={history}>              
            <AppRoutes />
          </Router>             
    </Provider>
  );
}

现在 AppRoutes 组件有以下方法

const RouteList = [
    {
        path: "/",
        component: Dashboard,
        guest: false,
        exact: true
    },
    {
        path: "/security_info",
        component: SecurityInfoPage,
        guest: false,
        exact: true
    },
]

class AppRoutes extends Component {

    componentDidMount() {
        ...here we fetch the login info from store
        isAuthenticated = true
    }   

    render() {
        ...if it has access token, it 
        return (
            <Switch>
                {RouteList.map((route, i) => (
                    route.guest === false 
                    ? <PrivateRoute isAuthenticated={isAuthenticated} key={i} {...route} /> 
                    : <AppRoute key={i} {...route} />
                    )
                )}
            </Switch>
        );
    }
}

因为 is_authenticated 为真,所以它转到 AppRoute.js 文件中的私有路由

const PrivateRoute = ({isAuthenticated,  component: Component, ...rest }) => (
   <Route 
        {...rest} 
        render={(props) => (
            isAuthenticated === true
              ? <DashboardLayout>
                            <Component {...props}/>
                        </DashboardLayout>
              : <Redirect to='/login' />
        )} 
    />
)

它转到具有多个组件的仪表板布局

<div className={'wrapper'}>
                <Navigation />
                <div className="page-content">
                    <Sidebar />
                    <div className="content-wrapper">
                        {children}
                        <MessageSideBar />
                        <Footer />
                    </div>
                </div>
            </div>

现在,当我单击不同的链接时,它会转到仪表板布局,其中其道具子项会发生更改,从而呈现整个仪表板,包括页眉、页脚、侧边栏。 编辑1: 这是侧边栏文件

class Sidebar extends Component {

componentDidMount = () => {
        it is requesting data from 3 api's
        this.props.dispatch(sidebarAction.sidebarDetail())
        this.props.dispatch(settingAction.getCreditAmount())
        this.props.dispatch(messageAction.getUnReadMessageCount())
    }
render(){
return(
   <ul>
    <li>
     <NavLink 
        exact={true} 
        to="/" >
        <span>Dashboard</span>
     </NavLink>
    </li>
    <li>
      <NavLink to="/security_info">
        <span>Security Information</span>
      </NavLink>
    </li>
   </ul>
)}

虽然有 10 多个 NavLink,但我只包含了 2 个并且还删除了不相关的类名

【问题讨论】:

  • 如果我是你,我会尝试为那些依赖于经过身份验证的用户的组件创建条件渲染。如果 auth bool 为 true,则显示这些组件(侧边栏、标题按钮等)。我不会让整个布局依赖于 auth 布尔值,只是那些实际上依赖于它的布局。您可以为此使用上下文 API 或 redux。另一种选择是对这些元素使用纯组件,这样它们就不会重新渲染,除非 auth bool 发生变化。
  • 请将代码贴在您创建链接的地方,即侧边栏。
  • @Rodrigo 先生,我不知道 Context API 以及如何使用纯组件,我正在寻找一种方法来停止重新渲染。
  • 纯组件允许您在父组件重新渲染但子组件的 prop 或状态值不重新渲染时避免重新渲染:reactjs.org/docs/react-api.html#reactpurecomponent 在这里您可以阅读有关 Context API 的信息: reactjs.org/docs/context.html
  • 你也可以看看这个:reactjs.org/docs/conditional-rendering.html

标签: reactjs react-redux react-router-dom


【解决方案1】:

方法不对

您的路由的结构类似于以下 sn-p,这将导致每次切换路由时重新渲染 Dashboard 组件。

<Route path="/subComponent" component={SubComponent}/>
const SubComponent = () => {
    return (
        <Dashboard>
            // Here is your content place
        </Dashboard>
    )
}

正确方法

但是,正确的解决方案是将路由直接放在Dashboard 组件中,您希望在其中呈现由布局 (Dashboard) 包裹的组件,如下所示:

<Dashboard>
    <DashboardMenu>
        <SideNav /> // e.g. containing links with history.push()
    </DashboardMenu>

    // here is the place where the components wrapped by the layout should be rendered, so place the routes here
    <Route path={...} component={() => <ComponentInsideDashboard />}
</Dashboard>

您应该已经在仪表板中呈现实际内容(动态内容,而不是静态Dashboard)。由于每条路由都返回包裹在Dashboard 中的动态组件,因此Dashboard 将被多次渲染。

更简单地说:由于您希望Dashboard 只呈现一次,因此您应该只在一个地方使用它。

不同布局的正确方式

如果您还想在没有布局 (Dashboard) 或多个不同布局的情况下呈现内容,您可以简单地使用嵌套路由。

export const BaseApplicationRoutes = () => {
    return (
        <BrowserRouter>
            <Switch>
                <Route path="/dashboard1" component={<Dashboard1 />}/>
                <Route path="/dashboard2" component={<Dashboard2 />}/>
                <Route path="/noDashboard" component={<NoDashboard />}/>
            </Switch>
        </BrowserRouter>
    )
}
<Dashboard1> // Dashboard2 could also look like this
    <Dashboard1Menu>
        <SideNav /> // e.g. containing links with history.push()
    </Dashboard1Menu>

    // Routes containing dynamic content
    <Route path={...} component={() => <ComponentWithDashboard1 />}
</Dashboard1>
<NoDashboard>
    // any content or even more routes rendering content without a layout
</NoDashboard>

【讨论】:

猜你喜欢
  • 2021-01-11
  • 2022-07-28
  • 1970-01-01
  • 1970-01-01
  • 2021-01-23
  • 1970-01-01
  • 2022-12-17
  • 1970-01-01
  • 2020-12-10
相关资源
最近更新 更多