我有一个反应本机网络应用程序。我尝试为动物创建一个过滤功能。通过过滤器函数返回的数据是由 api 调用生成的。我正在使用上下文来注入 api 调用。然后在组件中我尝试从组件的上下文中调用过滤器函数。
我正在使用 flatlist 来显示卡片上的动物。但例如,如果我尝试使用 Wolf 来过滤列表。什么也没发生。
这就是 api 调用:
export const fetchAnimalData = async (text) => {
const token = await retrieveToken();
try {
if (token) {
const response = await fetch(`${API_URL}/api/animals/?name=${text}`, {
method: "GET",
headers: {
Authorization: `Token ${token}`,
Accept: "application/json",
"Content-Type": "application/json",
},
});
return await response.json();
} else {
throw new Error(token);
}
} catch (error) {
console.error("There was a problem with the fetch operation:", error);
throw error;
}
};
这是上下文:
import React, { createContext, useEffect, useState } from "react";
import { fetchAnimalData } from "./animal/animal.service";
export const SearchAnimalContext = createContext();
export const SearchAnimalContextProvider = ({ children }) => {
const [searchAnimal, setSearchAnimal] = useState([]);
const [results, setResults] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const handleSearch = (text) => {
setSearchAnimal(text);
};
const filteredData = searchAnimal.filter((item) =>
item.name.toLowerCase().includes(searchAnimal.toLowerCase())
);
const performSearch = async (text) => {
setLoading(true);
setError(null);
fetchAnimalData(text)
.then((response2) => {
setResults(response2);
setIsLoading(false);
})
.catch((err) => {
setLoading(false);
setError(err);
});
};
return (
<SearchAnimalContext.Provider
value={{
filteredData,
searchAnimal,
setSearchAnimal,
handleSearch,
performSearch,
results,
loading,
error,
}}>
{children}
</SearchAnimalContext.Provider>
);
};
我从该组件的上下文中注入函数 PerformSearch :
export const SubCategoryScreen = ({ route, navigation }) => {
const [subCatgoryList, setSubCategoryList] = useState([]);
const [isLoading, setLoading] = useState(true);
const [searchAnimal, setSearchAnimal] = useState("");
const [input, setInput] = useState("");
const { performSearch } = useContext(SearchAnimalContext);
const [searchTimer, setSearchTimer] = useState(null);
const [results, setResults] = useState([]);
const { toggle, showAccordion } = useContext(ToggleContext);
const [toggleIcon, setToggleIcon] = useState(true);
const handleClickIcon = () => {
setToggleIcon(!toggleIcon);
};
const filteredData = subCatgoryList.filter((item) =>
item.name.toLowerCase().includes(searchAnimal.toLowerCase())
);
return (
<SafeArea>
{isLoading && (
<LoadingContainer>
<ActivityIndicator animating={true} color={MD2Colors.green200} />
</LoadingContainer>
)}
<Searchbar
placeholder="Searchie"
onChangeText={(text) => {
if (searchTimer) {
clearTimeout(searchTimer);
}
if (text.length === 0) {
console.log(text, "TEXT");
return null;
}
setInput(text);
setSearchTimer(setTimeout(performSearch(text), 1000));
}}
value={input}
/>
{results.length > 0 ? (
<CategoryList
data={results}
renderItem={({ item }) => {
return (
<>
<Spacer>
<SubCategoryInfoCard subcategories={item} />
</Spacer>
</>
);
}}
keyExtractor={(item) => item.id}
/>
) : (
<CategoryList
data={filteredData}
renderItem={({ item }) => {
return (
<>
<TouchableOpacity
onPress={() => navigation.navigate("groepen", { subcategories: item.id })}
disabled={
isLoading ||
(!item.hasOwnProperty("animals") && !item.hasOwnProperty("subcategories"))
}>
<Spacer>
<SubCategoryInfoCard subcategories={item} />
</Spacer>
</TouchableOpacity>
</>
);
}}
keyExtractor={(item) => item.id}
/>
)}
</SafeArea>
);
};
但是列表中没有任何内容被过滤。但是如果我在上下文组件中的这一行放置一个断点:
setResults(response2);
in devtools
然后它重新运行正确的结果。例如我搜索 Wolf
response2: Array(1)
0: {id: 8, name: 'Wolf', sort: 'Canis lupus', uis: false, cites: 'nvt', …}
length: 1
[[Prototype]]: Array(0)
如果我把api调用方法直接放在
SubCategoryScreen
组件中,里面有这个:
response.json().then((response2) => {
setResults(response2);
然后就可以了
问题:如何从平面列表中过滤特定的动物?
在
SubCategoryScreen
中,您使用:
const [results, setResults] = useState([]);
从未更新过。
performSearch
将更新上下文中的 results
,但不会更新 results
组件中的 SubCategoryScreen
状态
您可能想使用以下内容:
const { performSearch, results } = useContext(SearchAnimalContext);
同样,您可能还想从上下文中提取
loading
/error
。