【问题标题】:React-Router: Nested Routes and Parent re-renderReact-Router:嵌套路由和父级重新渲染
【发布时间】:2018-06-27 03:34:04
【问题描述】:

我正在使用 react-router v4 并且在嵌套路由方面遇到了一些问题。我的父路由是一个产品详细信息页面,它使用 componentDidMount() 中的 AJAX 请求来设置产品数据。

但是当我单击链接以呈现嵌套在详细信息页面中的路由时,父路由会重新呈现并且 AJAX 请求第二次吗?

这是一些简单的示例代码:

const App = () => (
  <Router>
    <Switch>
      <Route path="/login" component={LoginPage} />
      <Route path="/admin" component={AdminPage} />
    </Switch>
  </Router>
)

const AdminPage = ({match}) => (
  <Switch>
    <Route exact path={match.path} component={Home} />
    <Route path={`${match.path}/products/:id`} component={ProductDetails} />
    <Route path={`${match.path}/products`} component={ProductList} />
  </Switch>
)

class ProductDetails extends React.Component {
  constructor(){
    super();
    this.state = {
      name: '',
      price: ''
    };
  }
  componentDidMount(){
    API.getProductDetails((response) => {
      this.setState({
        name: response.name,
        price: response.price
      });
    })
  }
  render(){
    return(
      <div>
        <h1>{this.state.name}</h1>
        <p>{this.state.price}</p>
        <ul>
          <li><Link to={`${this.props.match.url}/stats}>Stats</Link></li>
          <li><Link to={`${this.props.match.url}/bids}>Bids</Link></li>
          <li><Link to={`${this.props.match.url}/third}>Third</Link></li>
        </ul>
        <Switch>
          <Route path={`${this.props.match.path}/stats} component={Stats} />
          <Route path={`${this.props.match.path}/bids} component={Bids} />
          <Route path={`${this.props.match.path}/third} component={Third} />
        </Switch>
      </div>
    );
  }
}

那么当我打开嵌套在其中的一个路由时,如何防止父组件 (ProductDetails) 重新渲染?感谢您的帮助!

【问题讨论】:

  • 当一个嵌套路由被点击时它会重新渲染,这是预期的行为。是不是嵌套Route被点击时调用componentDidMount的问题?
  • 是的,每次我单击其中一个嵌套路由时,componentDidMount() 都会触发重新发送 AJAX 请求 - 我想这样做,以便仅在第一次安装父组件时调用 AJAX 请求。
  • 我认为如果您在 ProductDetails 中删除了 Switch,它可能会跳过重新安装。从那里开始就不需要 Switch 了。 github.com/ReactTraining/react-router/issues/4578
  • IMO 最好有一条路线 &lt;Route path="/products/:id/:type" component={FooContainer} /&gt; 并根据类型在这条路线中处理您的请求。嵌套是不必要的。
  • 嘿,您找到解决方案了吗?我面临着完全相同的问题

标签: reactjs react-router


【解决方案1】:

在我的情况下,使用 render prop 而不是 component 并没有解决这个问题。 我的问题是关于 HOC,我不得不从路线中删除它:

<Route
  path="/:locale"
  render={({ match: { url } }) => (
    <Switch>
      <Route
        exact
        path={`${url}/login`}
        component={hocCausingIssue(LoginPage)}
      />
    </Switch>
  )}
/>

成为:

<Route
  path="/:locale"
  render={({ match: { url } }) => (
    <Switch>
      <Route exact path={`${url}/login`} component={LoginPage} />
    </Switch>
  )}
/>

// LoginPage
export default hocCausingIssue(LoginPage) // Now it no longer causes issue

【讨论】:

    【解决方案2】:

    我遇到了类似的问题,在尝试从子组件调用 Redirect 时,整个父组件都被重构了。 Here is the question I posted and answered myself haha,希望对你也有帮助!

    tl;dr:尝试更改应用程序的路由以使用渲染而不是组件。

    const App = () => (
      <Router>
        <Switch>
          <Route path="/login" render={() => <LoginPage />}
          <Route path="/admin" render={() => <AdminPage />}
        </Switch>
      </Router>
    )
    

    【讨论】:

      【解决方案3】:

      重新渲染父级似乎是 React 的预期行为。

      对于只执行一次 AJAX 请求的情况,您应该寻找的一种替代方法是在父组件挂载时执行它,这只会发生一次。

      例如,使用功能组件:

      function Route() {
          return (
              <Route path="/main" render={() => <Main/>} />
          );
      }
      
      function Main() {
          useEffect(() => {
              console.log("Main mounted");
              // execute ajax here
          }, []) // this empty dependency array turns it into a "componentDidMount" effect
          return (
              <div>
                  <h1>Main</h1>
                  <Route exact path="/main/tab1" render={() => <Tab1/>}/>
                  <Route exact path="/main/tab2" render={() => <Tab2/>}/>
              </div>
          );
      }
      
      function Tab1() {
          return (
              <div>Tab1</div>
          );
      }
      
      function Tab2() {
          return (
              <div>Tab2</div>
          );
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-07
        • 2017-11-15
        • 2022-01-13
        • 2021-12-28
        • 1970-01-01
        • 2018-06-06
        • 2017-12-20
        相关资源
        最近更新 更多