使用重定向时完全重建反应父组件 [英] React Parent Component completely reconstructed when using Redirect

查看:49
本文介绍了使用重定向时完全重建反应父组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试利用嵌套路由来保持屏幕上父组件的外观,并且当用户在选项卡结构中左右导航时,该选项卡式界面中的内容会更新.我不希望父组件重新挂载甚至重新渲染,只有子组件要更改.这是一个完全基于键盘的导航系统,所以我们没有使用链接或点击事件,只是在键盘上点击左/右/上/下/回车.

不幸的是,出于隐私原因,我无法分享我的确切代码,但这里是通用代码结构(显然不可编译,只是为了了解我们架构的要点).

在 App.js 中

class App 扩展组件 {使成为() {返回 (<div className="应用程序"><开关><路线路径=/"精确的匹配={真}组件={()=><主菜单/>}/><路线path="/category/:uniqueID"精确的组件={()=><CategoryComponent childArray=[child1, child2, child3]/>}/>/></开关>

);}}

在 CategoryComponent.js 中

class CategoryComponent extends Component {使成为() {var childRoutes;this.props.childArray.forEach(child => {childRoutes.push(<路线键=child.idpath={ `${this.props.match.path}/${child.path}` }组件={()=><子组件/>}/>);});返回 (<div className="CategoryComponent">...//一堆 UI 的东西放在这里,包括子组件的导航<开关>{ 子路由 }</开关>

);}}

最后,在 ChildComponent.js 中

class ChildComponent 扩展组件 {shouldComponentUpdate(nextProps) {//因为这个导航完全由键盘完成,//每个孩子都有一个选择或不选择的属性,它是从它的父母那里得到的,//所以只有当前选择的应该真正进行重定向如果 (!this.props.isSelected && nextProps.isSelected) {this.redirect = true;}}使成为() {变量重定向;如果(this.redirect){重定向 =<重定向to={ `${this.props.match.path}/${this.props.thisChildPath}` }/>;}返回 (<div className="ChildComponent">{ 重定向 }

);}}

希望以上所有内容都有意义,我认为我可以从我们疯狂的复杂应用程序中做到这一点.基本上:

  • 我们有一个应用程序,其路由使用唯一 ID,即.myApp.com/category/1234
  • 在此类别中,我们有一些选项卡可以导航到,例如蓝色、红色、黄色,对于每个选项卡,我们都希望将路线嵌套在上面的内部,并以类似 myApp.com/category/的内容结束1234/blue,只会更新屏幕的一部分

我遇到的问题是,无论我在哪里放置重定向,如果我使用精确或(非精确路径),或者如果我在重定向中使用 push 作为真,父组件总是重新安装.我最终得到了一个全新的父组件,它将清除保存在本地状态中的某些元素.应用程序永远不会重新安装,但父组件会.我只希望重新安装子组件,父组件应保持原样.最初 Category 组件甚至是一个高阶组件,我们将其切换为一个普通的组件类,但无论是否有条件地呈现特定情况,似乎也没有任何不同.

另外,我一直在玩这个codeandbox,并修改了原始代码以更紧密地匹配我的项目并利用链接和重定向,父应用程序组件似乎从未重新安装.所以......似乎有可能,我只是不确定我做错了什么.

任何帮助将不胜感激:)谢谢!

解决方案

这帮了我很多:https://github.com/ReactTraining/react-router/issues/6122

我意识到我们的应用程序的交换机路由使用了component,这导致了每次的重构.通过将这些全部切换到 render,问题就解决了 :D

所以 App.js 变成了这个:

class App 扩展组件 {使成为() {返回 (<div className="应用程序"><开关><路线路径=/"精确的匹配={真}渲染={()=><主菜单/>}/><路线path="/category/:uniqueID"精确的渲染={()=><CategoryComponent childArray=[child1, child2, child3]/>}/>/></开关>

);}}

I am trying to utilize nested routes in order to maintain the appearance of a parent component on screen, and as the user navigates left and right in a tab structure, the content in that tabbed interface updates. I do not want the parent component to remount or even re-render, only it's children to change. This is a completely keyboard-based navigation system, so we are not using Links or click events, just hitting left/right/up/down/enter on the keyboard.

Unfortunately, I cannot share my exact code for privacy reasons, but here is the general code structure (obviously not compilable, just to get the gist of what our architecture is like).

in App.js

class App extends Component {
  render() {
    return (
      <div className="App">
        <Switch>
          <Route
            path="/"
            exact
            match={ true }
            component={ () => <MainMenu/> }
          />
          <Route
            path="/category/:uniqueID"
            exact
            component={ () => <CategoryComponent childArray=[child1, child2, child3] /> }
          />
      />
        </Switch>
      </div>
    );
  }
}

in CategoryComponent.js

class CategoryComponent extends Component {
  render() {
    var childRoutes;
    this.props.childArray.forEach(child => {
      childRoutes.push(
        <Route
          key=child.id
          path={ `${this.props.match.path}/${child.path}` }
          component={ () => <ChildComponent/> }
        />
      );
    });

    return (
      <div className="CategoryComponent">
        ... // a bunch of UI stuff goes here, including the navigation for the child components
        <Switch>
          { childRoutes }
        </Switch>
      </div>
    );
  }
}

and finally, in the ChildComponent.js

class ChildComponent extends Component {
  shouldComponentUpdate(nextProps) {
    // because this navigation is done exclusively by keyboard,
    // each child has a property of selected or not that it gets from its parent,
    // so only the currently selected one should actually be doing the redirect
    if (!this.props.isSelected && nextProps.isSelected) {
      this.redirect = true;
    }
  }
  render() {
    var redirect;
    if (this.redirect) {
      redirect = 
        <Redirect
          to={ `${this.props.match.path}/${this.props.thisChildPath}` }
        />;
    }

    return (
      <div className="ChildComponent">
        { redirect }
      </div>
    );
  }
}

Hopefully all of the above made sense, it's as simple as I think I can make it from our crazy complex application. Basically:

The problem I am having is that it seems no matter where I place the redirects, if I use exact or (non-exact paths), or if I use push as true in the Redirect, the parent component ALWAYS remounts. I end up with an entirely new parent component, which will wipe out certain elements saved in local state. The App never remounts, but the Parent Component does. I only want the Child Components to remount, the parent should stay exactly as is. Originally the Category component was even a Higher Order Component, and we switched this to just one normal component class, but with or without conditionally rendering specific cases, didn't seem to make any different either.

Also, I have been playing around with this codesandbox, and adapted the original code to more closely match my project and utilize both links and redirects, and the parent app component never seemed to remount. So...it SEEMS like it's possible, I'm just not sure what I'm doing wrong.

Any help would be greatly appreciated :) thanks!

解决方案

This helped me out a ton: https://github.com/ReactTraining/react-router/issues/6122

I realized that our App's Switch Routing was using component, which was causing the reconstruction every time. By switching those all to render, the problem was solved :D

So App.js became this:

class App extends Component {
  render() {
    return (
      <div className="App">
        <Switch>
          <Route
           path="/"
            exact
            match={ true }
            render={ () => <MainMenu/> }
          />
          <Route
            path="/category/:uniqueID"
            exact
            render={ () => <CategoryComponent childArray=[child1, child2, child3] /> }
          />
      />
        </Switch>
      </div>
    );
  }
}

这篇关于使用重定向时完全重建反应父组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆