如何创建带有api调用和上下文的过滤器函数?

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

我有一个反应本机网络应用程序。我尝试为动物创建一个过滤功能。通过过滤器函数返回的数据是由 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);

然后就可以了

问题:如何从平面列表中过滤特定的动物?

javascript reactjs react-native react-context react-native-flatlist
1个回答
0
投票

SubCategoryScreen
中,您使用:

const [results, setResults] = useState([]);

从未更新过。

performSearch
将更新上下文中的
results
,但不会更新
results
组件中的
SubCategoryScreen
状态

您可能想使用以下内容:

const { performSearch, results } = useContext(SearchAnimalContext);

同样,您可能还想从上下文中提取

loading
/
error

© www.soinside.com 2019 - 2024. All rights reserved.