React-Router:嵌套路由和父级重新渲染

IT技术 reactjs react-router
2021-05-08 12:51:21

我正在使用 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) 重新渲染?感谢您的任何帮助!

3个回答

在我的情况下,使用renderprop 而不是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

我遇到了类似的问题,当尝试从子组件调用 Redirect 时,整个父组件都被重建。这是我发布并回答自己的问题哈哈,我希望它也能帮助你!

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

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

重新渲染父级似乎是 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>
    );
}