首页 > 解决方案 > 从 APII 过滤数据

问题描述

我在根据常规价格从 API 过滤数据时遇到问题。所以我遇到的错误有点愚蠢。这是错误 Data is not being iterable in theuseLayoutEffect。任何帮助将非常感激。非常感谢。这是沙盒链接。https://codesandbox.io/s/unruffled-currying-77y43?file=/src/books.js

import React, {useState, useEffect} from 'react'
import URL from '../utilis/URL';
const BookContext = React.createContext();
export default function BooksProvider({ children }) {
  
  const [data, setData] = useState([])
  const [filters, setFilters]= useState({
    regularPrice:"all",
    length:""
   
  })
  
  /*fetching data */ 
  const fetchData = async () => {
    const response = await fetch(URL);
    const result = await response.json();  
    console.log(result)
    setData(result);
  };

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

  const updateFilters = e => {
    const type = e.target.type;
    const filter = e.target.name;
    const value = e.target.value;
    let filterValue;
    if (type === "checkbox") {
      filterValue = e.target.checked;
    } else if (type === "radio") {
      value === "all" ? (filterValue = value) : (filterValue = parseInt(value));
    } else {
      filterValue = value;
    }
    setFilters({ ...filters, [filter]: filterValue });
  };

  /* filtering price books */ 
  React.useLayoutEffect(() => {
    let newBooks = [...data].sort((a, b) => a.regularPrice - b.regularPrice);
   
    if (regularPrice !== "all") {
      newBooks = newBooks.filter(item => {
        if (regularPrice === 0) {
          return item.regularPrice <10;
        } else if (regularPrice === 10) {
          return item.regularPrice > 10 && item.regularPrice < 20;
        } else {
          return item.regularPrice > 20;
        }
      });
    }
  }, [filters, data]);

 const { regularPrice } = filters;  
return (
    <BookContext.Provider value={{ data, filters, regularPrice, updateFilters, handleSelectCategory, setCurrentSelectedCategory, currentSelectedCategory }}>
      {children}
    </BookContext.Provider>
  );
}
export {BookContext, BooksProvider}
import React, { useContext } from 'react'
import { BookContext } from '../../context/books'

const Filters = () => {
    const {filters:{regularPrice, updateFilters}}= useContext(BookContext)
    return (
        <div>
              <p>Regular Price</p>
          <label>
            <input
              type="radio"
              name="regularPrice"
              id="all"
              value="all"
              checked={regularPrice === "all"}
              onChange={updateFilters}
            />
            all
          </label>
          <label>
            <input
              type="radio"
              name="regularPrice"
              value="0"
              checked={regularPrice === 0}
              onChange={updateFilters}
            />
            $0 - $10
          </label>
          <label>
            <input
              type="radio"
              name="regularPrice"
              value="10"
              checked={regularPrice === 10}
              onChange={updateFilters}
            />
            $10 - $20
          </label>
          <label>
            <input
              type="radio"
              name="regularPrice"
              value="20"
              checked={regularPrice === 20}
              onChange={updateFilters}
            />
            Over $20
          </label>
       
        </div>
    )
}

export default Filters

家长


import React,{useState, useEffect, useContext} from 'react'
import './Home.css'
import Books from './Books'
import {GiHamburgerMenu} from 'react-icons/gi'
import { BookContext } from "../../context/books";
import Filters from './Filters';
import Responsive from './Responsive'
const Home = () => {
   const {data, handleSelectCategory, currentSelectedCategory } 
   =useContext(BookContext)
   const[isCategoryOpen, setIsCategoryOpen]=useState(false)
  
  function closeCategory(){
    setIsCategoryOpen(false)
  }
   return (
        <div className='books__container' >
            <div className='responsive' >
              <GiHamburgerMenu onClick={()=> 
             setIsCategoryOpen(!isCategoryOpen)}/> 
              {isCategoryOpen ? <Responsive />:null}
            </div>  
            <h1 className='categories'>Categories</h1>
            {Object.keys(data).map((key, index)=>{
            let books = data[key];
            return (              
              <div key={key} onClick={() => handleSelectCategory(key)} 
              className='books__list' >
              {books[0].category}     
              </div>                 
              );})}   
              <Filters />
              <Books category={currentSelectedCategory} />
        </div>
    )
}

export default Home

孩子


import React,{useContext, ReactFragment} from 'react'
import { CartContext } from '../../context/cart';
import HoverBooks from './HoverBooks';
import { useHistory, Link } from "react-router-dom";
import { UserContext } from '../../context/user';
const Books = ({category}) => {
const {addToCart }= useContext(CartContext)
const { user } = React.useContext(UserContext);

    return (     
        <div className='books__main'>      
        {category.slice(0, 5).map((book) => {   
          console.log(book)    
          return(
           <React.Fragment key={book.id}>
           <HoverBooks 
           key={book.id}
           {...book}       
           />    
           <div className='book__content'>
            <li className='book__name'>{book.bookName}</li>
             <h4 className='book__prop'>By: {book.by}</h4>
             <h4  className='book__prop'>Narreted by: {book.Narreted || 
           book["Narreted by"]}</h4>
             <h4  className='book__prop'>Length: {book.length || book["Length"]} 
            </h4>
             <h4  className='book__prop'>Release Date: {book.ReleaseDate}</h4>
             <h4  className='book__prop'>Language: {book.Language}</h4>
             <h4  className='book__prop'>Rating: {book.rating}</h4>
           </div>           
           <div className='book__adt'> 
           <h4>Regular Price: {book.RegularPrice}</h4>
           {user.authToken ? (
           
           <button onClick={() => 

              addToCart(book)
           }
           >Add to cart</button>  
           ) : (
            <Link to="/login" className="adt__login">
            Login to buy books
           </Link>
        )}
           </div>
       </React.Fragment>
        )})}
      </div>
     
    )
}
export default Books

标签: javascriptarraysjsonreactjs

解决方案


我设法通过转换result对象Object.values并在setData.

  const fetchData = async () => {
    const response = await fetch(URL);
    const result = await response.json();
    const resultArray = Object.values(result);

    setCurrentSelectedCategory(resultArray[0]['category']);
    //    setCurrentSelectedCategory(result[Object.keys(result)[0]]);
    setData(resultArray);
  };

没有错误

我不确定这个应用过滤器应该如何工作。如果您可以说明完整应用程序的图片,我可能会了解更多信息(例如,如果您按照某种教程进行操作,您可以指向该资源的 URL 等)。

正如我之前在评论中所说,您似乎不能直接使用 api 响应的结果。如果您在浏览器中看到 heroku 应用程序的端点,则结构很清楚。

我还建议您避免在与您的代码和框示例相同的文件夹中使用相同的文件名,例如 (books.jsBooks.js),即使操作系统允许两者都存在。


推荐阅读