Как создать функцию поиска в нативном приложении React?

У меня есть собственное приложение для реагирования. И у меня есть функция поиска. Проблема, с которой я столкнулся, заключается в том, что функция поиска работает только тогда, когда в текстовое поле введено все слово.

Так например работает Эдельхерт. Но если пользователь вводит: Эд - то ничего не происходит.

И если пользователь ждет секунду в текстовом поле поиска. Затем выскакивает эта ошибка:

VM270:1  Uncaught SyntaxError: Unexpected identifier 'Promise'

Итак, API поиска выглядит:

import { API_URL } from "@env";
import { retrieveToken } from "../../services/authentication/token";

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;
    }
};

и контекст поиска:

/* eslint-disable prettier/prettier */

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 [input, setInput] = useState("");

    useEffect(() => {
        fetchAnimalData();
    }, [searchAnimal]);

    const performSearch = async (text) => {
        setLoading(true);
        setError(null);
        setTimeout(() => {
            fetchAnimalData(text)
                .then((response2) => {
                    setResults(response2);
                    setLoading(false);
                })
                .catch((err) => {
                    setLoading(false);
                    setError(err);
                });
        });
    };
    return (
        <SearchAnimalContext.Provider
            value = {{
                results,
                setResults,
                searchAnimal,
                setSearchAnimal,
                input,
                setInput,
                performSearch,
                loading,
                error,
            }}>
            {children}
        </SearchAnimalContext.Provider>
    );
};

И компонент с полем поиска:

import React, { useContext, useState } from "react";

import { AccordionItemsContext } from "../../../services/accordion-items.context";
import { AnimalDetailToggle } from "../../../components/general/animal-detail-toggle-view";
import { CategoryContext } from "../../../services/category/category.context";
import { CategoryInfoCard } from "../components/category-info-card.component";
import { SafeArea } from "../../../components/utility/safe-area.component";
import { SearchAnimalContext } from "../../../services/search-animal.context";
import { Searchbar } from "react-native-paper";

export const CategoryScreen = ({ navigation }) => {
    useContext(AccordionItemsContext);  
    const { loading, categoryList } = useContext(CategoryContext);
    const { performSearch, results, setInput, input } = useContext(SearchAnimalContext);
    const [searchTimer, setSearchTimer] = useState(null);

    return (
        <SafeArea>
            {loading && (
                <LoadingContainer>
                    <ActivityIndicator animating = {true} color = {MD2Colors.blue500} />
                </LoadingContainer>
            )}
            <Searchbar
                placeholder = "search animalll"
                onChangeText = {(text) => {
                    if (searchTimer) {
                        clearTimeout(searchTimer);
                    }
                    if (!text.length) {
                        setInput("");
                        return;
                    }

                    setInput(text.substring(0));
                    setSearchTimer(setTimeout(performSearch(text), 1000));
                }}
                value = {input}
            />

        </SafeArea>
    );
};

А для бэкэнда я использую Django. Одно из мнений такое:

from django_filters.rest_framework import DjangoFilterBackend
# from WelzijnAdmin.permissions import AdminReadOnly
from rest_framework import permissions, viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from django.contrib.auth.decorators import permission_required
from rest_framework import filters

from .models import Animal, Category
from .serializers import (AnimalSerializer, CategorySerializer,
                          MainGroupSerializer)


class AnimalViewSet(viewsets.ModelViewSet, permissions.BasePermission):

    queryset = Animal.objects.all().order_by('name')
    serializer_class = AnimalSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]

    filterset_fields = ['name']
    search_fields = ['name']


class CategoryViewSet(viewsets.ModelViewSet, permissions.BasePermission):
    """
    This API endpoint allows for the viewing of animal categories.

    All categories include their direct subcategories and animals.

    - To view a specific category, append the url with its [/id](/api/categories/1/).
    - To get all top-level categories use [/main_groups](/api/categories/main_groups). 
    """

    def get_serializer_class(self):
        if hasattr(self, 'action') and self.action == 'main_groups':
            return MainGroupSerializer
        return CategorySerializer

    queryset1 = Category.objects.all().order_by('name')
    queryset = CategorySerializer.eager_load(queryset1)
    serializer_class = get_serializer_class(super)

    permission_classes = (IsAuthenticated,)

    @action(methods=['get'], detail=False)
    # @permission_required("category")
    def main_groups(self, request):
        """
        Returns a list of top level Categories.

        - To view a specific category, append the url with its [/id](/api/categories/1/).
        """
        main_groups = Category.objects.filter(category_id__isnull=True)
        serializer = self.get_serializer(main_groups, many=True)

        return Response(serializer.data)

И если я пойду в

http://127.0.0.1:8000/api/animals/

а затем выберите фильтр и введите в поле поиска el, затем отфильтруются животные, у которых есть буквы el:

[
    {
        "id": 15,
        "name": "Blauwgele Ara",
       
    },
    {
        "id": 71,
        "name": "Edelhert",

    {
        "id": 19,
        "name": "Edelpapegaai",
}]

или я набираю ar:


 {
        "id": 15,
        "name": "Blauwgele Ara",
     
    },
    {
        "id": 24,
        "name": "Bobakmarmot",
}

Что я уже сделал? Конечно, много гуглил. Смотрю ролики на ютубе. Например этот:

https://thewikihow.com/video_i1PN_c5DmaI

Но я не вижу ошибки, мешающей частичному поиску слова.

Вопрос: как реализовать частичный поиск по слову?

Что возвращает PerformSearch setSearchTimer(setTimeout(performSearch(text), 1000));?

Michael Bahl 27.06.2024 20:05

@МайклБал. Вы имеете в виду, какое значение возвращается? Или что это значит? Это означает, что не каждый раз будет вызываться база данных

mightycode Newton 27.06.2024 22:53

поскольку на основе вашего API вы будете отправлять текст: например, «Эд» вместо «Эдельхерт», убедитесь, что ваш API действительно ищет животных, в которых есть «Эд».

displayname 28.06.2024 03:51

@отображаемое имя. Возможно, я вас не правильно понимаю». Но это, конечно, пример. Я имею в виду в целом - когда набирается слово... ti, то в результатах поиска должны всплывать elvar, eland, слон. Я использую бэкэнд Django. Пользователь может выполнить поиск по части слова, а затем всплывут все слова целиком с первыми введенными символами.

mightycode Newton 28.06.2024 08:21
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
4
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ах хорошо. Я этого не знал. Я тоже учусь. Но что я сделал. В бэкэнде я изменил это:

class AnimalViewSet(viewsets.ModelViewSet, permissions.BasePermission):

    queryset = Animal.objects.all().order_by('name')
    serializer_class = AnimalSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]

    filterset_fields = ['name']
    search_fields = ['name']

    def get_queryset(self):
        qs = Animal.objects.all()
        name = self.request.query_params.get('name')
        if name is not None:
            qs = qs.filter(name_icontains=name)
        return qs

И в интерфейсе я изменил это:

export const fetchAnimalData = async (text) => {
    const token = await retrieveToken();
    try {
        if (token) {
            const response = await fetch(`${API_URL}/api/animals/?search=${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;
    }
};

И теперь это работает.

Другие вопросы по теме