在所有路线上反应加载屏幕?

时间:2018-09-15 21:44:56

标签: reactjs react-router

我了解如何使用statecomponentDidMount()来获得微调器屏幕,但是我将如何在所有路径之间创建一个加载屏幕,而不必在每条路由中都写componentDidMount()组件?

我的app.js文件

class App extends Component {

  constructor(props) {
    super(props);
    this.child = React.createRef();
  }

  onWaypoint = () => {
    this.child.current.navChangeHandler();
  }

  render() {

    let routes = (
      <Switch>    
        <Route exact path="/projects" component={Projects} />
        <Route exact path="/about" component={About} />
        <Route exact path="/gallery" component={Gallery} />
        <Route exact path="/" component={Home} />
        <Redirect exact to="/" />
      </Switch>
    )

    return (
      <BrowserRouter>
        <div className="App" styleName="main-wrapper">
          <Layout>
              {routes}
              <Navigation ref={this.child} />
          </Layout>
        </div>
      </BrowserRouter>

    );
  }
}

我希望能够在这些路线之间看到一个微调器。

3 个答案:

答案 0 :(得分:1)

您可以在子组件上创建HOC包装函数。然后,如果需要,您可以将HOC方法传递给子级,然后让该子级调用该方法。

例如:

父母:

export default WrappedComponent => {
  class Wrapper extends Component {
    state = { isLoading: true };

    componentDidUpdate = prevProps => {
      if (this.props.location !== prevProps.location) {
        this.setState({ isLoading: true });
      }
    };

    doneLoading = () => this.setState({ isLoading: false })

    render = () => (
      <WrappedComponent
        doneLoading={this.doneLoading}
        isLoading={this.state.isLoading}
        {...this.props}
      />
    );
  }
  return withRouter(Wrapper);
};

孩子(可以从孩子的this.props内部访问传递的HOC方法/状态):

export default class Child extends PureComponent {

  componentDidMount = () => {
    fetch("someURL")
      .then(response => response.json())
      .then(json => this.setState({ list: json }), () => this.props.doneLoading());
  };

  render = () =>
    this.props.isLoading 
      ? <Spinner />
      : <DisplayList list={...this.state.list} />
}

缺点是每个子组件都需要导入Spinner并检查isLoading是否为假。

限制

为了使它在高度嵌套的组件之间工作,您很有可能希望/需要集成Redux。此外,您需要让已安装的容器在每次更改路线时调度一个操作来更新/重置isLoading Redux状态。无论哪种方式,如果您想变干,它都不是一个简单而优雅的解决方案。


示例

工作示例(此示例只是通过超时设置/取消了HOC状态):https://codesandbox.io/s/2zo8lj44pr

Wrapper.js

import React, { Component, Fragment } from "react";
import { withRouter } from "react-router";
import Header from "./Header";
import Spinner from "./Spinner";

export default WrappedComponent => {
  class Wrapper extends Component {
    state = { isLoading: true };

    componentDidMount = () => this.setTimer();

    componentDidUpdate = prevProps => {
      if (this.props.location !== prevProps.location) {
        this.clearTimer();
        this.setState({ isLoading: true }, () => this.setTimer());
      }
    };

    clearTimer = () => clearTimeout(this.timeout);

    timer = () => this.setState({ isLoading: false }, () => this.clearTimer());

    setTimer = () => (this.timeout = setTimeout(this.timer, 3000));

    render = () => (
      <Fragment>
        <Header />
        {this.state.isLoading
          ? <Spinner />
          : <WrappedComponent {...this.props} />
      </Fragment>
    );
  }
  return withRouter(Wrapper);
};

index.js

import React from "react";
import { render } from "react-dom";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import Home from "../components/Home";
import Schedule from "../components/Schedule";
import Wrapper from "./components/Wrapper";

render(
  <BrowserRouter>
    <Switch>
      <Route exact path="/" component={Wrapper(Home)} />
      <Route path="/schedule" component={Wrapper(Schedule)} />
    </Switch>
  </BrowserRouter>,
  document.getElementById("root")
);

答案 1 :(得分:0)

答案 2 :(得分:0)

我的尝试:

return <Switch>
    <Route
        exact
        path={loading ? '*' : '/'}
        component={LoadingRoute} />
    <Route
        path={loginPaths}
        component={LoginLayout}
    />
    <Route
        path={adminPaths}
        component={AdminLayout}
    />
    <Route component={NotFound} />
</Switch>

在这种情况下,loginPathsadminPaths都没有路径/,因此默认的加载路径是/。如果根路径很重要,则可以使用;路径,因此它不会与任何内容匹配。我正在使用react-router-transition中的AnimatedSwitch,因此过渡之间的状态很​​重要。有了这个,您的App会说何时加载。