javascript - 从 APII 过滤数据
问题描述
我在根据常规价格从 API 过滤数据时遇到问题。所以我遇到的错误有点愚蠢。这是错误 Data is not being iterable in the
useLayoutEffect。任何帮助将非常感激。非常感谢。这是沙盒链接。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
解决方案
我设法通过转换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.js
和Books.js
),即使操作系统允许两者都存在。
推荐阅读
- python - Python read_excel 忽略数据
- php - 解析错误:语法错误,意外的“隐藏”(T_STRING)
- php - 如何使用 PHP 将字符串更改为 JSON 格式结构?
- vba - 如何搜索完全粗体的段落?
- excel - 分配给 Excel 中的图形图标时,宏无法正常工作。但它在通过 VBA IDE 运行时工作
- sqlite - 从 SQLite 中的两个表中随机选择
- c# - 按下 Arduino 按钮后如何在 C# 应用程序上执行操作?
- c# - 如何在 xamarin android 中使用这个库(smarteist Android-Image-Slider)?
- thorntail - 如何在 thorntail 中设置相对路径日志记录?
- kotlin - Kotlin Flow 的 GroupBy 运算符