在 React 中读取本地 JSON 文件时出现问题,使用 API 工作正常

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

我对 React 比较陌生,在读取本地 JSON 文件时遇到问题。奇怪的是,当我尝试从 API 读取数据时,一切都工作得很好。有人可以帮助我了解可能导致这种差异的原因以及如何解决它吗?

下面,我提供了我的代码片段以及相应的 StackBlitz 示例以供参考。

https://stackblitz.com/edit/react-wrni65?file=src%2Fcomponents%2FProductListing.jsx,src%2Fdata%2Fphotos.json

import React, { useState, useEffect } from 'react';
import axios from 'axios';
import '../App.css';
import Photos from '../data/photos.json';
// import './App.css';
import { Link, useNavigate } from 'react-router-dom'; // Assuming you're using React Router

const ProductListing = () => {
  const [products, setProducts] = useState([]);
  const [filteredProducts, setFilteredProducts] = useState([]); // State for search results
  const navigate = useNavigate(); // Import useNavigate hook

  const [cart, setCart] = useState(() => {
    // Load existing cart from localStorage
    const storedCart = localStorage.getItem('cart');
    return storedCart ? JSON.parse(storedCart) : [];
  });

  const addToCart = (product) => {
    const newCart = [...cart, product];
    setCart(newCart);
    localStorage.setItem('cart', JSON.stringify(newCart)); // Store updated cart
  };

  const [error, setError] = useState(null);
  const [currentPage, setCurrentPage] = useState(1);
  const productsPerPage = 50;
  const [searchTerm, setSearchTerm] = useState(''); // Search state

  useEffect(() => {
    const fetchProducts = async () => {
      try {
        const response = await axios.get('./data/photos.json');
        setProducts(response.data);
        setFilteredProducts(response.data); // Initialize filtered products
      } catch (error) {
        setError(error);
      }
    };
    fetchProducts();
  }, []); // Calculate indices for slicing the array

  // Handle search input changes
  const handleSearchChange = (event) => {
    setSearchTerm(event.target.value);
  };

  // Perform search filtering when the search term changes
  useEffect(() => {
    const newFilteredProducts = products.filter((product) =>
      product.title.toLowerCase().includes(searchTerm.toLowerCase())
    );
    setFilteredProducts(newFilteredProducts);
    setCurrentPage(1); // Reset pagination when search changes
  }, [searchTerm, products]);

  // Calculations for pagination (using filteredProducts)
  const indexOfLastProduct = currentPage * productsPerPage;
  const indexOfFirstProduct = indexOfLastProduct - productsPerPage;
  const currentProducts = filteredProducts.slice(
    indexOfFirstProduct,
    indexOfLastProduct
  );

  // const indexOfLastProduct = currentPage * productsPerPage;
  // const indexOfFirstProduct = indexOfLastProduct - productsPerPage;
  // const currentProducts = products.slice(
  //   indexOfFirstProduct,
  //   indexOfLastProduct
  // );

  const handlePageChange = (pageNumber) => {
    setCurrentPage(pageNumber);
  };

  const renderPagination = () => {
    const pageNumbers = [];
    for (let i = 1; i <= Math.ceil(products.length / productsPerPage); i++) {
      pageNumbers.push(i);
    }
    return (
      <nav>
            
        <ul className="pagination">
               
          {pageNumbers.map((number) => (
            <li
              key={number}
              className={
                currentPage === number ? 'page-item active' : 'page-item'
              }
            >
                     
              <a
                onClick={() => handlePageChange(number)}
                href="#"
                className="page-link"
              >
                        {number}
                       
              </a>
                    
            </li>
          ))}
              
        </ul>
           
      </nav>
    );
  };

  return (
    <div className="product-container">
      <input
        type="text"
        placeholder="Search..."
        value={searchTerm}
        onChange={handleSearchChange}
        className="search-input"
      />
         
      {error ? (
        <p className="error-message">Error fetching products</p>
      ) : (
        <>
                     {/* Added for pagination container */}
               
          <div className="product-grid">
                  
            {currentProducts.map((product) => (
              <div className="product-item" key={product.id}>
                {/*         {product.id} */}
                        
                <img
                  src={product.thumbnailUrl}
                  alt={product.title}
                  style={{ width: '50px', marginRight: '10px' }}
                  className="product-image"
                  onClick={() => navigate(`/reviews/${product.id}`)} // Navigate to review page
                />
                <p className="product-id">{product.id}</p>
                <button onClick={() => addToCart(product)}>Add to Cart</button>
                       
              </div>
            ))}
                 
          </div>
               {renderPagination()}
          <Link to="/checkout" className="checkout-button">
            Go to Checkout
          </Link>
              
        </>
      )}
        
    </div>
  );
};

export default ProductListing;
reactjs json api axios
1个回答
0
投票

正在使用该文件,还是仍在发出 API 请求?您可以在此处从项目导入 JSON 数据:

import Photos from '../data/photos.json';

但你从不使用它。相反,您尝试在此处通过 AJAX 获取它:

const response = await axios.get('./data/photos.json');

但是,此文件不作为应用程序结果输出的一部分托管。所以服务器返回的是 HTML。 (也许是404页面,也许是应用程序的主页等等)

由于您已经导入了所需的数据,因此无需发出 AJAX 请求来获取相同的数据。您可以完全删除

useEffect
fetchProducts
并将状态值初始化为导入的数据:

const [products, setProducts] = useState(Photos]);
const [filteredProducts, setFilteredProducts] = useState(Photos);
© www.soinside.com 2019 - 2024. All rights reserved.