如何修改我的代码,以便能够在将卡片显示在页面上之前按库存和价格对卡片进行排序?

问题描述 投票:0回答:1

我正在使用 TypeScript 开发一个 React 应用程序,用于显示商店的卡片。我从一个 API 获取这些卡的数据,还需要从另一个 API 检索每张卡的其他信息,例如库存和价格。我的问题在于实现允许用户在将卡片显示在页面上之前按库存和价格对卡片进行排序的功能。但是,由于股票和价格信息是在卡片呈现后异步获取的(在 Card.tsx 中,我将结果与我的商店、股票和价格中的数据连接起来),我无法对它们进行正确排序。 我现在正在考虑两种可能的解决方案:

  1. 在将卡片显示在数组之类的东西上之前加载它们,以便能够在显示之前对它们进行排序。
  2. 找到一种在卡片加载后对其进行排序的方法。 我一直没能找到一种方法来做到这两点 在应用“库存”过滤器之前我遇到了同样的问题,但我通过执行完全不同的 search-stock.tsx 使其工作,因为我无法使其工作 这是search.tsx的代码
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import { useAuth } from "../components/AuthContext";
import Cart from "../components/cart";
import Card from "../components/card";
import { useNavigate } from "react-router-dom";

const Search = () => {
  const [results, setResults] = useState([]);
  const { search } = useLocation();
  const query = new URLSearchParams(search).get("query");
  const { user, fetchLatestUserDetails } = useAuth();
  const [noResults, setNoResults] = useState(false); // New state to track "no results" condition
  const [filterInStock, setFilterInStock] = useState(true);
  const navigate = useNavigate();
  const [currentPage, setCurrentPage] = useState(1);
  const [totalPages, setTotalPages] = useState(0);
  const pageSize = 10; // New constant to define the number of items per page

  useEffect(() => {
    fetchLatestUserDetails().catch(console.error);
  }, []);

  const applyFilters = () => {
    const basePath = filterInStock ? "/stock/search" : "/search";
    const searchQuery = query ? `?query=${query}` : "";
    navigate(`${basePath}${searchQuery}`);
  };

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch(
        `https://api.scryfall.com/cards/search?unique=prints&include_multilingual=true&q=${query}`
      );
      const data = await response.json();
      if (data.code === "not_found") {
        // Check if the response indicates no results
        setNoResults(true); // Set noResults to true if no results were found
        setResults([]); // Ensure results is empty
      } else {
        // delete all data that has lang different from "en" or "es"
        data.data = data.data.filter(
          (card: { lang: string }) => card.lang === "en" || card.lang === "es"
        );
        console.log(data.data.length);
        setTotalPages(Math.ceil(data.data.length / pageSize)); // Calculate total pages
        //if data.data.length is 0, set noResults to true
        if (data.data.length === 0) {
          setNoResults(true);
          setResults([]);
        } else {
          setResults(data.data); // Set the results if found
          setNoResults(false); // Reset noResults to false
        }
      }
    };

    if (query) {
      fetchData().catch(console.error);
    }
  }, [query, currentPage]);

  const goToNextPage = () => {
    setCurrentPage((prev) => (prev < totalPages ? prev + 1 : prev));
  };

  const goToPrevPage = () => {
    setCurrentPage((prev) => (prev > 1 ? prev - 1 : prev));
  };

  return (
    <div className="searchpage">
      <div className="filters">
        <h1>Filtros</h1>
        <div>
          <input
            type="checkbox"
            id="stockCheckbox"
            checked={filterInStock}
            onChange={(e) => setFilterInStock(e.target.checked)}
          />
          <label htmlFor="stockCheckbox">En Stock</label>
        </div>
        {/* Add Apply Filters Button */}
        <button onClick={applyFilters}>Aplicar Filtros</button>
      </div>
      <div className="search-content">
        {noResults ? (
          <h3>No se encontraron resultados para: {query}</h3>
        ) : (
          <div>
            <h3>Resultados de busqueda para: {query}</h3>
            <div className="order-buttons">
              <div>
                <button onClick={goToPrevPage}>Anterior</button>
                <span>{currentPage}</span>
                <button onClick={goToNextPage}>Siguiente</button>
              </div>
            </div>
            <ul>
              {results
                .slice((currentPage - 1) * pageSize, currentPage * pageSize)
                .map(
                  (
                    // its posible that some properties return null, so you can use the optional chaining operator to avoid errors
                    card: {
                      id: string | null;
                      name: string | null;
                      mana_cost: string | null;
                      colors: Array<any> | null;
                      set_name: string | null;
                      lang: string | null;
                    },
                    index: number
                  ) => (
                    // style list so it doesn't have bullets
                    <li key={index} style={{ listStyle: "none" }}>
                      {card &&
                        card.id &&
                        card.name &&
                        card.set_name &&
                        card.lang && (
                          <Card
                            id={card.id}
                            name={card.name}
                            set_name={card.set_name}
                            lang={card.lang}
                          />
                        )}
                    </li>
                  )
                )}
            </ul>
          </div>
        )}
      </div>
      <div>
        {user ? (
          <Cart items={user.cart} userConnected={true} />
        ) : (
          <Cart items={null} userConnected={false} />
        )}
      </div>
    </div>
  );
};

export default Search;

如前所述,我已经尝试过两种可能的解决方案,但无法使它们发挥作用。 不知道有没有更好的办法

reactjs typescript api sorting
1个回答
0
投票

一些值得探索的想法:

© www.soinside.com 2019 - 2024. All rights reserved.