【问题标题】:Created multi-Filtered buttons in React but the list won't display everytime I click on other filter button在 React 中创建了多过滤按钮,但每次单击其他过滤按钮时列表都不会显示
【发布时间】:2020-03-12 07:17:00
【问题描述】:

我成功创建了多个过滤按钮。但是,我注意到,当我第一次单击一个过滤按钮显示居住在英国的学生时,列表显示过滤结果,然后我单击另一个过滤按钮显示居住在美国的学生,列表只是空白,我的控制台显示数组是空的。我不知道发生了什么。

import React, { Component } from 'react';
import profiles from '../data/berlin.json';

export class FaceBook extends Component {
  constructor(props){
    super(props);
    this.state = {
        profilelist: profiles,
        filtered: profiles
    }
}
showProfile = () =>{
  return this.state.profilelist.map((eachProfile,i)=>{
    let studentBoolean;
    if(eachProfile.isStudent) {
      studentBoolean = "Student";
    } else {studentBoolean = "Teacher"}
      return(
        <div className="profilecard" key={i}>
          <div className="profileimage"><img src={eachProfile.img} alt="Actor"/></div>
          <div className="profilecontent">
            <ul>
              <li><strong>First Name:</strong> {eachProfile.firstName}</li>
              <li><strong>Last Name:</strong> {eachProfile.lastName}</li>
              <li><strong>Country:</strong> {eachProfile.country}</li>
              <li><strong>Type:</strong> {studentBoolean}</li>
            </ul>
          </div>
      </div>
      )
  })
}
showAll = () =>{

  this.setState({
    profilelist: profiles
  })
}

showEngland = () =>{
  this.setState({
    profilelist: profiles,
    filtered: profiles
  })
  let filterEngland = [...this.state.profilelist];

  let newList = filterEngland.filter(item => {
    const lc = item.country.toLowerCase();
    const filter = "england";
    return (lc === filter);
  })
  console.log(newList);
  this.setState({
    profilelist: newList,
    filtered: newList
  })
}

showUSA = () =>{
  this.setState({
    profilelist: profiles,
    filtered: profiles
  })

  let filterUSA = [...this.state.profilelist];

  let newusaList = filterUSA.filter(item => {
    const lc = item.country.toLowerCase();
    const filter = "usa";
    return (lc === filter);
  })
  this.setState({
    profilelist: newusaList,
    filtered: newusaList
  })
}

  render() {
    console.log(this.state.profilelist);
    return (
      <div>
      <div className="menubar">
        <button onClick={this.showAll}>All</button>
        <button onClick={this.showEngland}>England</button>
        <button onClick={this.showUSA}>USA</button>
      </div>
      <div className="profileTable">
      {this.showProfile()}
      </div>

      </div>
    )
  }
}

export default FaceBook

如您所见,我创建了 3 个按钮“All”、“England”、“USA”。我还为每个按钮创建了 3 个函数。 all 按钮重置state.profilelist,而英国和美国显示过滤结果。我尝试添加

this.setState({
    profilelist: profiles,
    filtered: profiles
  })

在英格兰和美国函数的开头,以便在过滤之前重置列表,但它不起作用....

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    您不需要为每个过滤器创建一个函数,只需创建一个处理所有过滤的函数即可。不要修改profilelist,你所有的过滤都应该修改filtered数组。

    // filter profiles by country
    filterByCountry = country => {
    
      if (!country || typeof country !== "string") {
        return;
      }
    
      this.setState(prevState => {
        return {
          filtered:
            country.toLowerCase() === "all"
              ? this.state.profilelist
              : prevState.profilelist.filter(
                  item =>
                    item &&
                    item.country &&
                    item.country.toLowerCase() === country.toLowerCase()
                )
        };
      });
    };
    

    显示配置文件功能

    showProfile = () => {
      return this.state.filtered.map((eachProfile, i) => (
        <div className="profilecard" key={i}>
          <div className="profileimage">
            <img src={eachProfile.img} alt="Actor" />
          </div>
          <div className="profilecontent">
            <ul>
              <li>
                <strong>First Name:</strong> {eachProfile.firstName}
              </li>
              <li>
                <strong>Last Name:</strong> {eachProfile.lastName}
              </li>
              <li>
                <strong>Country:</strong> {eachProfile.country}
              </li>
              <li>
                <strong>Type:</strong>{" "}
                {eachProfile.isStudent ? "Student" : "Teacher"}
              </li>
            </ul>
          </div>
        </div>
      ));
    };
    

    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.0/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.21.1/babel.min.js"></script>
    <div id="root"></div>
    
    <script>
    
    const profiles = [
      {
        firstName: "James",
        lastName: "Peter",
        country: "England",
        isStudent: true,
        img: "https://img.icons8.com/officel/16/000000/edit-user-female.png"
      },
      {
        firstName: "Jane",
        lastName: "Jones",
        country: "usa",
        isStudent: false,
        img: "https://img.icons8.com/officel/16/000000/edit-user-female.png"
      },
      {
        firstName: "Michael",
        lastName: "Ballack",
        country: "Germany",
        isStudent: false,
        img: "https://img.icons8.com/officel/16/000000/edit-user-female.png"
      },
      {
        firstName: "Mary",
        lastName: "Jane",
        country: "England",
        isStudent: false,
        img: "https://img.icons8.com/officel/16/000000/edit-user-female.png"
      },
      {
        firstName: "Charlie",
        lastName: "Barack",
        country: "usa",
        isStudent: true,
        img: "https://img.icons8.com/officel/16/000000/edit-user-female.png"
      },
      {
        firstName: "Will",
        lastName: "Ozil",
        country: "Germany",
        isStudent: true,
        img: "https://img.icons8.com/officel/16/000000/edit-user-female.png"
      }]
      
    </script>
    
    <script type="text/babel">
    
    class App extends React.Component {
      constructor() {
        super();
        this.state = {
          profilelist: profiles,
          filtered: profiles
        };
      }
      
      filterByCountry = country => {
        if (!country || typeof country !== "string") {
          return;
        }
    
        this.setState(prevState => {
          return {
            filtered:
              country.toLowerCase() === "all"
                ? this.state.profilelist
                : prevState.profilelist.filter(
                    item =>
                      item &&
                      item.country &&
                      item.country.toLowerCase() === country.toLowerCase()
                  )
          };
        });
      };
    
      showProfile = () => {
        return this.state.filtered.map((eachProfile, i) => (
          <div className="profilecard" key={i}>
            <div className="profileimage">
              <img src={eachProfile.img} alt="Actor" />
            </div>
            <div className="profilecontent">
              <ul>
                <li>
                  <strong>First Name:</strong> {eachProfile.firstName}
                </li>
                <li>
                  <strong>Last Name:</strong> {eachProfile.lastName}
                </li>
                <li>
                  <strong>Country:</strong> {eachProfile.country}
                </li>
                <li>
                  <strong>Type:</strong>{" "}
                  {eachProfile.isStudent ? "Student" : "Teacher"}
                </li>
              </ul>
            </div>
          </div>
        ));
      };
    
      render() {
    
        return (
          <div>
            <div className="menubar">
              <button onClick={() => this.filterByCountry("All")}>All</button>
              <button onClick={() => this.filterByCountry("England")}>
                England
              </button>
              <button onClick={() => this.filterByCountry("usa")}>USA</button>
            </div>
            <div className="profileTable">{this.showProfile()}</div>
          </div>
        );
      }
    }
    
    ReactDOM.render(
        <App />,
        document.getElementById('root')
    );
    </script>

    【讨论】:

      【解决方案2】:

      问题归结为 setState 是异步的,

      当你这样做时

      this.setState({
          profilelist: profiles,
          filtered: profiles
        })
        let filterEngland = [...this.state.profilelist];
      

      您希望 profilelist 的状态在此之前被重置

      let filterEngland = [...this.state.profilelist];
      

      行被调用。但是 setState 是异步的。您的filterEngland 将仅分配有以前过滤的元素,当您对其运行过滤器时,列表变为空。

      有很多方法可以解决这个问题。 setState 有一个回调函数,只有在状态正确更新后才会执行。 this.setState({}, cb)

      这样你就可以像这样重写函数。

      showUSA = () => {
        this.setState({
          profilelist: profiles,
          filtered: profiles
        },() => {
           let filterUSA = [...this.state.profilelist];
           let newusaList = filterUSA.filter(item => {
             const lc = item.country.toLowerCase();
             const filter = "usa";
             return (lc === filter);
           })
           this.setState({
             profilelist: newusaList,
             filtered: newusaList
           })
        })
      
       }
      

      但我会要求您重新考虑整体代码的编写方式。你在迭代 并打印profilelist,而不是显示filtered 每个按钮单击应该只更新filteredprofileList 将保留为您的主列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-10-13
        相关资源
        最近更新 更多