
[英]Getting error in reactjs TypeError: Cannot read properties of undefined (reading 'filter')
[英]TypeError: Cannot read properties of undefined (reading 'filter') and undefined error - React
提示:本站为国内最大中英文翻译问答网站,提供中英文对照查看,鼠标放在中文字句上可显示英文原文。
我的 API 通话有问题。 我想为我的项目创建一个搜索栏,数据来自 API。 但是,当我添加过滤器 function 时出现错误。
TypeError: Cannot read properties of undefined (reading 'filter')
为了解决这个问题,我添加了可选的链接运算符,但它也不起作用,因为我得到“未定义”。 此外,为了获取值,我使用了 useEffect 钩子,但我不确定它是否是正确的解决方案。 我认为我的组件是在我的 API 调用未执行之前呈现的。 你能帮我修一下吗?
这是我的主要组成部分:
import "../App.css"
import APICall from "./APICall.js"
import Filter from "./Filter.js"
import {useState} from "react"
function App() {
const [datum, setDatum] = useState([])
return (
<div className="App">
<Filter datum={datum} />
<APICall setDatum={setDatum} />
</div>
)
}
export default App
这是我进行 API 调用时的子组件:
import React from 'react'
import axios from "axios"
import { useState, useEffect } from 'react'
function APICall({setDatum}) {
const [loading, setLoading] = useState(false)
useEffect(() => {
const fetchAPI = async () => {
setLoading(true)
try {
const res = await axios(`https://api.spoonacular.com/food/products/search?query=yogurt&apiKey=`)
setDatum(res.data.products)
// console.log(datum)
}
catch(err) {
console.log(err)
}
setLoading(false)
}
fetchAPI()
}, [])
if (loading === true) {
return <div>Loading...</div>
}
}
export default APICall
这是我遇到问题的另一个子组件:
import {useState, useEffect} from "react"
function Filter({datum}) {
const [filterText, setFilterText] = useState("")
const handleInput = (e) => {
setFilterText(e.target.value)
}
useEffect(() => {
const handleFilter = async () => {
try {
const filtered = await datum.title?.filter(item => {
return Object.keys(item).some(key =>
item[key].toString().toLowerCase().includes(filterText.toLocaleLowerCase())
)
})
console.log(filtered)
}
catch (err) {
console.log(err)
}
}
handleFilter()
}, [filterText])
return (
<div>
<input type="text" placeholder="Please enter the name of the the food" onChange={handleInput} value={filterText} />
{datum.map((el, id) => (
<div key={id} className="items">
<img src={el.image} alt={el.title} />
<p>{el.title}</p>
</div>
))}
</div>
)
}
export default Filter
编辑这是我从 API 获得的一些数据:
0: {id: 201369, title: 'Yoplait Yogurt, Lactose Free Yogurt, Peach, 6.0 oz', image: 'https://spoonacular.com/productImages/201369-312x231.jpeg', imageType: 'jpeg'}
1: {id: 415304, title: 'Noosa Key Lime Finest Yoghurt, 8 OZ', image: 'https://spoonacular.com/productImages/415304-312x231.jpeg', imageType: 'jpeg'}
2: {id: 89557, title: 'Yoplait Light Yogurt with Granola, Blueberry, Fat Free, 12 oz, 2 Cups', image: 'https://spoonacular.com/productImages/89557-312x231.png', imageType: 'png'}
我必须进行很多更改才能使其正常工作。 一些注意事项:你想按标题过滤,所以你做了datum.title.filter
数据是一个数组,它没有标题属性,这就是你得到未定义的原因。 您必须使用datum.filter
,并且filter
function 不是 promise,您不需要使用await
。 我还为过滤后创建了另一个state,并让原始数据保持不变,以便能够将itens重置为原始项目,否则如果您过滤了原始itens,它们会丢失。 我使Filter.js
中的代码更简单,不需要useEffect,当你输入你改变filteredDatum的state和列表被过滤,我也是一个很好的搜索逻辑,搜索单独的词,例如,如果标题是“yougurt lactose 100”,如果搜索是“yog 100”,它会找到
应用程序.js
import "../App.css";
import APICall from "./APICall.jsx";
import Filter from "./Filter.jsx";
import { useState } from "react";
function App() {
const [datum, setDatum] = useState([]);
const [datumFiltered, setDatumFiltered] = useState([]);
return (
<div className="App">
<Filter datum={datum} datumFiltered={datumFiltered} setDatumFiltered={setDatumFiltered} />
<APICall setDatum={setDatum} setDatumFiltered={setDatumFiltered} />
</div>
);
}
export default App;
过滤器.js
function Filter({ datum, datumFiltered, setDatumFiltered }) {
const handleFilter = (e) => {
const filterText = e.target.value.toLowerCase();
const wordsToFilter = filterText.split(" ");
datumFiltered = datum.filter((item) => {
return wordsToFilter.every((word) => item.title.toLowerCase().includes(word));
});
setDatumFiltered(datumFiltered);
};
return (
<div>
<input type="text" placeholder="Please enter the name of the the food" onChange={handleFilter} />
{datumFiltered.map((el, id) => (
<div key={id} className="items">
<img src={el.image} alt={el.title} />
<p>{el.title}</p>
</div>
))}
</div>
);
}
export default Filter;
APICall.js
import React from "react";
import axios from "axios";
import { useState, useEffect } from "react";
//REMOVE THIS FUNCTION
const axiosDummyCall = async () => {
return [
{
id: 201369,
title: "Yoplait Yogurt, Lactose Free Yogurt, Peach, 6.0 oz",
image: "https://spoonacular.com/productImages/201369-312x231.jpeg",
imageType: "jpeg",
},
{
id: 415304,
title: "Noosa Key Lime Finest Yoghurt, 8 OZ",
image: "https://spoonacular.com/productImages/415304-312x231.jpeg",
imageType: "jpeg",
},
{
id: 89557,
title: "Yoplait Light Yogurt with Granola, Blueberry, Fat Free, 12 oz, 2 Cups",
image: "https://spoonacular.com/productImages/89557-312x231.png",
imageType: "png",
},
];
};
function APICall({ setDatum, setDatumFiltered }) {
const [loading, setLoading] = useState(false);
useEffect(() => {
const fetchAPI = async () => {
setLoading(true);
try {
let datum = await axiosDummyCall(); //REPLACE WITH REAL CALL
setDatum(datum);
setDatumFiltered(datum);
} catch (err) {
console.log(err);
}
setLoading(false);
};
fetchAPI();
}, []);
if (loading === true) {
return <div>Loading...</div>;
}
}
export default APICall;
关于第二个 state:
如果你只有一个 state,例如: ['yogurt', 'yogurt fat free', 'ketchup']
,如果你输入yogurt
,则 state 会变成['yogurt', 'yogurt fat free']
, ketchup
丢了。 如果您继续输入yogurt fat
,现在 state 再次更改为['yogurt fat free']
,则丢失了 itens yogurt
和ketchup
。 例如,您现在清除过滤器以再次显示所有项目,现在唯一出现的项目是yogurt fat free
,因为原来的 state 已更改,其他项目丢失。 您将不得不再次调用 API 再次填写列表。
这就是为什么我添加了第二个 state,这样整个列表就不会被触及,而且你总是可以再次找回所有的元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.