【问题标题】:Struggling to filter by category properly努力按类别正确过滤
【发布时间】:2022-11-15 01:55:31
【问题描述】:
import React, { useEffect, useState } from "react";
import Loading from "./Loading";

function App() {
    const url = "https://course-api.com/react-tabs-project";
    const [loading, setLoading] = useState(true);
    const [data, setData] = useState([]);
    
    async function setCompany(companyName) {
        await getData();
        const newData = data.filter((info) => info.company === companyName);
        setData(newData);
    }

    async function getData() {
        try {
            const response = await fetch(url);
            const data = await response.json();
            setData(data);
            setLoading(false);
        } catch (err) {
            setLoading(false);
            console.error(`ERROR  ==> ${err}`);
        }
    }

    useEffect(() => {
        getData();
    }, []);

    if (loading) {
        return <Loading></Loading>; // simple loading screen
    }
    return (
        <main>
            <div className="top-wrapper">
                <h2>Experience</h2>
                <div className="underline"></div>
            </div>
            {data.map((item) => {
                const { id, order, title, dates, duties, company } = item;
                return (
                    <article key={id}>
                        <h3>{title}</h3>
                        <span className="company">{company}</span>
                        <p>{dates}</p>
                        <ul>
                            {duties.map((duty, index) => {
                                return <li key={index}>{duty}</li>;
                            })}
                        </ul>
                        <button>MORE INFO</button>
                    </article>
                );
            })}
            <div className="nav-buttons">
                <button
                    onClick={() => {
                        setCompany("TOMMY");
                    }}
                    className="nav-btn"
                >
                    TOMMY
                </button>
                <button
                    onClick={() => {
                        setCompany("BIGDROP");
                    }}
                    className="nav-btn"
                >
                    BIGDROP
                </button>
                <button
                    onClick={() => {
                        setCompany("CUKER");
                    }}
                    className="nav-btn"
                >
                    CUKER
                </button>
            </div>
        </main>
    );
}

export default App;

Sooo ...基本上我正在尝试过滤由返回的数组拿来并让它只显示我想要的类别(我将其称为“公司而不是我的代码中的类别”),具体取决于我单击的按钮,如代码中“导航按钮”div 中所示。 我第一次点击一个按钮时它工作正常,但第二次它没有显示任何东西,好像它是过滤来自已经过滤的数组显然没有返回任何结果。

【问题讨论】:

  • 我想每次单击此处的按钮时都不需要调用 API .... 您解释的第二次单击场景也不清楚 tbh
  • 发生的情况是,当我单击三个类别按钮之一时,数据仅设置为具有相应类别的数组,这意味着我的状态值(数据一)从 3 个元素的数组减少到 1,下次我单击一个按钮,getData 函数仅过滤 1 个数组而不是 3 个,因为其他 2 个已在第一次单击时被过滤掉,结果什么也不返回
  • 添加我的想法和方法作为答案,请检查..

标签: javascript reactjs arrays


【解决方案1】:
  • 您不需要在每个过滤器上调用相同的 API,因为如果我没记错的话,它会返回相同的数据。
  • 您可以通过将所选公司存储在状态中来过滤具有派生状态的数据,即在每次渲染时,它根据所选公司计算。
  • 最终使用过滤后的数据进行渲染。

这是完整的例如

import React, { useEffect, useState } from "react";
import Loading from "./Loading";

function App() {
  const url = "https://course-api.com/react-tabs-project";
  const [loading, setLoading] = useState(true);
  const [data, setData] = useState([]);
  const [selectedCompany, setSelectedCompany] = useState("");  // store the company on click

  const filteredData = selectedCompany ? data.filter(info=> info.company === selectedCompany) : data;  // filter data based on selected company
  
  async function getData() {
    try {
      const response = await fetch(url);
      const data = await response.json();
      setData(data);
      setLoading(false);
    } catch (err) {
      setLoading(false);
      console.error(`ERROR  ==> ${err}`);
    }
  }

  useEffect(() => {
    getData();
  }, []);

  if (loading) {
    return <Loading></Loading>; // simple loading screen
  }
  return (
    <main>
      <div className="top-wrapper">
        <h2>Experience</h2>
        <div className="underline"></div>
      </div>
      {filteredData.map((item) => {
        const { id, order, title, dates, duties, company } = item;
        return (
          <article key={id}>
            <h3>{title}</h3>
            <span className="company">{company}</span>
            <p>{dates}</p>
            <ul>
              {duties.map((duty, index) => {
                return <li key={index}>{duty}</li>;
              })}
            </ul>
            <button>MORE INFO</button>
          </article>
        );
      })}
      <div className="nav-buttons">
        <button
          onClick={() => {
            setSelectedCompany("TOMMY");
          }}
          className="nav-btn"
        >
          TOMMY
        </button>
        <button
          onClick={() => {
            setSelectedCompany("BIGDROP");
          }}
          className="nav-btn"
        >
          BIGDROP
        </button>
        <button
          onClick={() => {
            setSelectedCompany("CUKER");
          }}
          className="nav-btn"
        >
          CUKER
        </button>
      </div>
    </main>
  );
}

export default App;

【讨论】:

    【解决方案2】:
    // Get the oportunity to learn about promises, and you will save so much time. ;)
    
    import React, { useEffect, useState } from "react";
    
    function App() {
        const url = "https://course-api.com/react-tabs-project";
        const [loading, setLoading] = useState(true);
        const [data, setData] = useState([]);
        const [companyName, setCompanyName] = useState("");
    
        async function setCompany(companyName) {
            getData();
            const newData = setData(newData);
        }
    
        function getData(companyName) {
            setCompanyName(companyName);
    
            fetch(url)
                .then((res) => res.json())
                .then((info) => {
                    console.log(info);
                    return companyName
                        ? info.filter((info) => info.company == companyName)
                        : info;
                })
                .then((res) => {
                    console.log(res);
                    return setData(res);
                })
                .catch((err) => {
                    setLoading(false);
                    console.error(`ERROR  ==> ${err}`);
                });
        }
    
        useEffect(() => {
            getData();
        }, []);
    
        return (
            <main>
                <div className="top-wrapper">
                    <h2>Experience</h2>
                    <div className="underline"></div>
                </div>
                {data.map((item) => {
                    const { id, order, title, dates, duties, company } = item;
                    return (
                        <article key={id}>
                            <h3>{title}</h3>
                            <span className="company">{company}</span>
                            <p>{dates}</p>
                            <ul>
                                {duties.map((duty, index) => {
                                    return <li key={index}>{duty}</li>;
                                })}
                            </ul>
                            <button>MORE INFO</button>
                        </article>
                    );
                })}
                <div className="nav-buttons">
                    <button
                        onClick={() => getData("TOMMY")}
                        className="nav-btn"
                    >
                        TOMMY
                    </button>
                    <button
                        onClick={() => getData("BIGDROP")}
                        className="nav-btn"
                    >
                        BIGDROP
                    </button>
                    <button
                        onClick={() => getData("CUKER")}
                        className="nav-btn"
                    >
                        CUKER
                    </button>
                </div>
            </main>
        );
    }
    
    export default App;
    

    【讨论】:

    • 想过做这样的事情,但最终改用 async await 但它没有用,谢谢你
    【解决方案3】:

    用这两行更新这两个方法:

    async function setCompany(companyName) {
        const response=await getData(); //THIS ONE
        const newData = response.filter((info) => info.company === companyName);
        setData(newData);
    }
    
    async function getData() {
        try {
            const response = await fetch(url);
            const data = await response.json();
            setData(data);
            setLoading(false);
            return data;// And THIS ONE
        } catch (err) {
            setLoading(false);
            console.error(`ERROR  ==> ${err}`);
        }
    }
    

    【讨论】:

      【解决方案4】:

      尝试在过滤器之前放置一个检查案例,以确保您的数组不为空。

       async function setCompany(companyName) {
              await getData();
              {data ? 
                const newData = data.filter((info) => info.company === companyName);
               :
              null}
              setData(newData);
          }
      

      我认为您的部分问题是当您调用按钮单击获取数据时,在运行过滤器逻辑之前未设置您的状态。我会查看您的功能逻辑并问自己这是做到这一点的最佳方法,我是否尝试在我的回复之前或之后进行过滤。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-09
        • 2015-12-23
        • 2014-05-11
        • 2021-05-18
        • 1970-01-01
        • 1970-01-01
        • 2011-09-09
        • 1970-01-01
        相关资源
        最近更新 更多