【问题标题】:re-rendering issues when using HOC for loader使用 HOC 加载程序时的重新渲染问题
【发布时间】:2017-12-07 07:29:29
【问题描述】:

我正在构建一个应用程序,其中有大量页面,每个页面都需要加载器图标来显示数据何时来自服务器但尚未到达,但如果根本没有数据则不显示任何内容。我可以在不使用高阶组件(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

【问题讨论】:

  • 显示“mapStateToProps”函数,我看不到你的“isRequesting”变量...
  • 我不知道您为什么要对这样的组件进行如此复杂的处理。首先简化您的代码。
  • 你能告诉我我应该在哪里改进吗?
  • 我认为问题出在 componentDidMount 但无法解决问题
  • 我将添加一个示例来说明我将如何做到这一点,对于 redux 或其他人来说真的没关系。您应该有 2 个正常工作的组件。之后添加 redux

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


【解决方案1】:

我做了一些超级简单的事情,而且肯定有需要改进的地方。 但它解决了您想要的问题,如果您有“loadedData”标志,则显示数据,如果没有,则显示加载程序。

代码链接: 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"));

【讨论】:

    猜你喜欢
    • 2018-10-08
    • 1970-01-01
    • 2022-11-16
    • 1970-01-01
    • 2013-07-30
    • 2011-06-03
    • 2020-08-06
    • 2020-09-22
    • 2019-04-05
    相关资源
    最近更新 更多