子路径阻止父路径的渲染

时间:2016-12-16 17:19:40

标签: reactjs react-router

我有一个使用react-router的反应应用程序。我使用普通路由,但这是组件代表我的路由的方式

<Routes>
    <Route component={CoreLayout}>
        <Route component={AppLayout}
            onEnter={fetchData}>
            <Route path='dashboard'
                onEnter={fetchStatistics}
                component={Dashboard}>
        </Route>
    </Route>
</Routes>

现在的情况

首先,应用程序布局将在从服务器获取必要数据(如用户数据)时阻止每个渲染。然后,如果我们有数据,我们可以踩到子路由,就像在这种情况下的Dashboard路由,我们正在加载页面的内容。

目标

问题在于这个策略,我们将显示一个空白的白页,直到主路线上的onEnter得到解决。

为了避免这种情况,我想加载AppLayout组件,但不启动子路由上的onEnter函数。为此,我可以显示子组件将加载的等待微调器,并且在加载数据时,我可以开始加载子项的数据。

TL;博士

问题是,如何在未加载子路由的onEnter的情况下使父布局呈现,而不是

1 个答案:

答案 0 :(得分:1)

您可以让onEnter在其<Dashboard>方法中启动其数据提取,而不是使用component(Will|Did)Mount。它保持state.loaded布尔值,在state.loaded = false时显示一个微调器。

class Dashboard extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      loaded: false
    }
  }

  componentWillMount() {
    // mock data fetch call that uses a promise
    fetchStatistics()
      .then(resp => resp.json())
      .then(data => {
        this.setState({
          loaded: true,
          data
        })
      })
  }

  render() {
    // if data hasn't been loaded, render a spinner
    if (!this.state.loaded) {
      return <Spinner />
    }
    // data has been loaded, render the dashboard
    return (
      <div>...</div>
    )
  }
}

编辑:

它不处理数据加载错误,但这里是 应该工作的通用数据加载HOC的示例(尚未测试):

/*
 * @Component is the component to render
 * @fetchData is a function which fetches the data. It takes
 *   a callback function to trigger once data fetching has
 *   completed.
 */
const withData = (Component, fetchData) => {
  return class WithData extends React.Component {
    constructor(props) {
      super(props)
      this.state = {
        loaded: false
      }
    }

    componentWillMount() {
      this.props.fetchData(() => {
        this.setState({ loaded: true })
      })
    }

    render() {
      return this.state.loaded ? (
        <Component {...this.props} />
      ) : (
        <Spinner />
      )
    }
  }
}

用法

function fetchStatistics(callback) {
  fetch('/api/dashboard')
    .then(resp => resp.json())
    .then(data => {
      dispatch(dashboardData(data))
      callback()
    })
})

<Route
  path='dashboard'
  component={withData(Dashboard, fetchStatistics} />