首页 > 解决方案 > 复选框和新组件,工作不规律

问题描述

您好我正在尝试使用复选框的数据构建一个新组件,为此我有以下代码:

import React from "react";
import BottomScrollListener from "react-bottom-scroll-listener";
import ThingsQuery from "./../querys/ThingsQuery";
import "./styles/Things.scss";

export default class Things extends React.Component {
  constructor() {
    super();
    this.displayData = [this.createPag()];
  }

  state = {
    sort: "popular",
    page: 1,
    featured: false,
    allPages: false,
  };

  createPag = (onNull = () => {}) => {
    return (
      <ThingsQuery
        page={this.state.page}
        sort={this.state.sort}
        featured={this.state.featured}
        onNull={onNull}
      />
    );
  };

  handleSortClick = (e) => {
    const sort = e.target.innerText.trim().toLowerCase();
    this.setState({ sort, page: 1, allPages: false }, () => {
      this.displayData = [this.createPag()];
    });
  };

  changePage = () => {
    if (!this.state.allPages) {
      const currentPage = this.state.page + 1;
      this.setState({ page: currentPage });
      const page = this.createPag(() => {
        this.setState({ allPages: true });
      });
      if (!this.state.allPages) {
        this.displayData.push(page);
      }
    }
  };

  handleChangeFeatured = (e) => {
    const featured = e.target.checked;
    console.log("onChangeFeatured");
    console.log(featured);
    this.setState({ page: 1, allPages: false, featured: featured }, () => {
      console.log("State changed");
      this.displayData = [this.createPag()];
    });
  };

  render() {
    return (
      <div className="things col-xs-1 text-center">
        <BottomScrollListener onBottom={this.changePage} />
        <div>
          <div className="custom-control custom-switch">
            <input
              onChange={this.handleChangeFeatured}
              type="checkbox"
              className="custom-control-input"
              id="customSwitch1"
              checked={this.state.featured}
            />
            <label className="custom-control-label" for="customSwitch1">
              Featured
            </label>
          </div>
          <div className="btn-group" role="group" aria-label="Basic example">
            <button
              onClick={this.handleSortClick}
              type="button"
              className="btn btn-secondary"
            >
              Popular
            </button>
            <button
              onClick={this.handleSortClick}
              type="button"
              className="btn btn-secondary"
            >
              Newest
            </button>
            <button
              onClick={this.handleSortClick}
              type="button"
              className="btn btn-secondary"
            >
              Latest
            </button>
          </div>
          <div className="container">
            <div className="card-columns">{this.displayData}</div>
          </div>
        </div>
      </div>
    );
  }
}

如您所见,我有一个复选框,它的选中值是由 state.featured 获得的。

这会正确加载如果我输入代码featured=True,加载它,如果我输入 false 也可以。

问题是尝试更改浏览器上的值时。

当我点击开关时,这个变化,值也发生变化,并且createPag,完全执行,但<ThingsQuery .... />在第一次点击时不起作用,我需要将选中的值更改2次,当然,在此之后,我得到了我想要的相反数据。

我该如何解决这个问题,为什么<ThingsQuery.../>在第一次点击时不运行?

谢谢

标签: javascriptreactjsbootstrap-4

解决方案


存储为局部实例变量的值,即this.displayData在更改时不会导致重新渲染。它们必须处于状态,并通过setState更改来触发重新渲染。

因此,在您的情况下,您调用setStatechange sortand allPages,然后状态更改和随后的重新渲染之后,您this.displayDatasetState回调中 change 。由于重新渲染已经完成,并且更改局部实例变量不会导致重新渲染,因此在下一次运行之前没有任何变化并且setState使用该 new 调用重新渲染displayData

如果您希望更改this.displayData导致重新渲染,它应该处于状态。任何影响渲染内容的值都应该处于状态。


推荐阅读