使用HOC进行加载时重新渲染问题

时间:2017-07-04 01:03:31

标签: javascript reactjs redux immutable.js higher-order-components

我正在构建一个应用程序,其中有大量页面,每个页面都需要加载程序图标,以显示数据何时来自服务器但尚未到达,但如果根本没有数据则不显示内容。我可以在没有使用高阶组件(HOC)的情况下显示这一点,但是在每个组件中这样做都很乏味。我希望加载器代码可以重用,以便我可以在任何需要的地方使用它。但我正面临着这个问题。

  

如果有数据,则没有问题。如果根本没有数据,那么   加载器保持加载和加载,而不是显示内容。

我必须在componentDidMount中使用if (!this.props.size)来获取数据,因为如果我不这样做,组件将连续重新渲染,如果我这样做,如果有数据,组件将不会重新渲染但如果根本没有数据,则会使用加载图标连续重新渲染组件。

这是代码

class Logs extends React.PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      show: false,
    };
  }
  componentDidMount() {
    // this.props.requestLogs();
    if (!this.props.logs.size) {
      this.props.requestLogs();
    }
  }

  //componentWillUnmount() {
    //document.body.removeEventListener("", this.props.requestLogs());
  //}


  renderLogs() {
    const { logs } = this.props;
    return logs.size > 0
      ? logs.valueSeq().map(log => {
          return (
            <div className="card" key={log.get("_id")}>
              <li className="row">
                <div className="col-md-6">
                  <a
                    onClick={() =>
                      this.handleDialog(log.get("_id"), log.get("error_stack"))}
                  >
                    {log.get("error_message")}
                  </a>
                </div>
                <div className="col-md-6 text-right">
                  <a
                    className="text-danger"
                    onClick={() => this.handleDelete(log.get("_id"))}
                  >
                    Delete
                  </a>
                </div>
              </li>
            </div>
          );
        })
      : <p>No Content</p>;
  }
  render() {
    const { logs, isRequesting } = this.props;
    return (
      <div className="container">
        <div className="row mg-btm-md">
          <div className="col-xs-6"> <h1>Logs</h1></div>
        </div>
        <ul className="list-group">
          {this.renderLogs()}
          {this.state.show ? this.props.dialog : null}
        </ul>
      </div>
    );
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(
  Loader("isRequesting")(Logs)
);


const Loader = prop => WrappedComponent => {
  return class Loader extends React.PureComponent {
    render() {
      return this.props[prop]
        ? <div className="earth-spinning">
            <img
              src={EarthSpinning}
              alt="spinner"
              style={{ margin: "0 auto" }}
            />
          </div>
        : <WrappedComponent {...this.props} />;
    }
  };
};

export default Loader;

完整代码在这里https://gist.github.com/SanskarSans/b30c085ffacf01c58b66f128096746cc

1 个答案:

答案 0 :(得分:0)

我做了一些非常简单的事情,肯定有改进的地方。 但它解决了你想要的问题,如果你有一个&#34; loadedData&#34;你显示数据,如果没有显示加载器。

链接到代码: https://codepen.io/tzookb/pen/VWdeyE

代码:

class SomeComponent extends React.Component {
  render() {
    return <div>Im a basic component</div>;
  }
}

function withLoader(WrappedComponent) {
  return class extends React.Component {
    render() {
      if (this.props.loadedData) {
        return <WrappedComponent {...this.props} />;        
      } else {
        return <h1>Loading...</h1>;
      }
    }
  };
}

let SomeComponentWithLoader = withLoader(SomeComponent);


ReactDOM.render(<SomeComponentWithLoader loadedData={false} />, document.getElementById("app"));