【问题标题】:Set debounced search in ReactJS在 ReactJS 中设置去抖动搜索
【发布时间】:2021-07-12 06:04:26
【问题描述】:

我是 ReactJS 的新手。但习惯于使用 VueJS。以前,我在 VueJS 中开发项目。但是在 ReactJS 中,我在设置分页时遇到了困难。

每当用户更改搜索值时,应将页码重置为 1 并调用 API 来获取结果。

这给我带来了麻烦。有人可以帮忙吗?

问题是如果我多次更改搜索值而不更改页面,它不会再次调用 API,因为页面值没有更改。这是我的代码。

import React, {useCallback, useEffect, useState, useMemo, useRef} from 'react';
import {useHistory, useLocation} from "react-router-dom";
import _ from 'lodash';
const queryString = require('query-string');
import {Page, Card, DataTable, Filters, Link, Stack, Pagination, Spinner} from '@shopify/polaris';

function usePrevious(value) {
    const ref = useRef();
    useEffect(() => {
        ref.current = value;
    });
    return ref.current;
}

export default function App() {

    const params = queryString.parse(location.search);

    const [from, setFrom] = useState(0);
    const [to, setTo] = useState(0);
    const [total, setTotal] = useState(0);
    const [hasPrevious, setHasPrevious] = useState(false);
    const [hasNext, setHasNext] = useState(false);
    const [page, setPage] = useState(params.page ? parseInt(params.page) : 1);
    const [queryValue, setQueryValue] = useState(params.search ? params.search : null);
    const [items, setItems] = useState([]);
    const [loading, setLoading] = useState(true);

    const queryParams = useMemo(() => {
        let queryParamsObject = {};
        if (page > 1) queryParamsObject.page = page;
        if (queryValue) queryParamsObject.search = queryValue;
        return queryParamsObject;
    }, [page, queryValue]);

    const prevPage = usePrevious(page);
    const prevQueryValue = usePrevious(queryValue);

    const handleFiltersQueryChange = useCallback((value) => setQueryValue(value), []);
    const handleQueryValueRemove = useCallback((value) => setQueryValue(null),[]);
    const handleFiltersClearAll = useCallback(() => handleQueryValueRemove(), [handleQueryValueRemove]);

    const rows = useMemo(() => {
        return items.map(item => {
            return [
                <Link removeUnderline url={`/items/${item.id}`}>{item.title}</Link>,
                item.email
            ];
        });
    }, [items]);

    const fetchItems = useCallback((params) => {

        setLoading(true);
        window.axios.get(`/items`, {params}).then((response) => {

            setItems(response.data.data);
            setFrom(response.data.from);
            setTo(response.data.to);
            setTotal(response.data.total);
            setHasPrevious(Boolean(response.data.prev_page_url));
            setHasNext(Boolean(response.data.next_page_url));
            setLoading(false);
        });
    }, []);

    
    const debouncedSearch = useCallback(_.debounce((params) => {
        if (params.page === page) {
            history.push({pathname: '/items', search: queryString.stringify(params)});
            fetchItems(params);
        } else {
            setPage(1);
        }
    }, 1000), []);

    useEffect(() => {
        if (typeof prevQueryValue !== "undefined" && prevQueryValue !== queryValue) {
            debouncedSearch(queryParams);
        } else {
            history.push({pathname: '/items', search: queryString.stringify(queryParams)});
            fetchItems(queryParams);
        }
    }, [page, queryValue]);

    return (
        <Filters
            queryValue={queryValue}
            filters={[]}
            onQueryChange={handleFiltersQueryChange}
            onQueryClear={handleQueryValueRemove}
            onClearAll={handleFiltersClearAll}
            queryPlaceholder="Filter items"
        />
        <DataTable
            columnContentTypes={[
                'text',
                'text',
            ]}
            headings={[
                'Col1',
                'Col2',
            ]}
            rows={rows}
            footerContent={`Showing ${from} to ${to} of ${total} results`}
        />
        {hasPrevious || hasNext ? <div className="pagination"><Stack distribution="center"><Pagination hasPrevious={hasPrevious} hasNext={hasNext} onPrevious={() => setPage(parseInt(page) - 1)} onNext={() => setPage(parseInt(page) + 1)} /></Stack></div> : null}
    );
}

【问题讨论】:

    标签: reactjs polaris


    【解决方案1】:

    我弄错了。只需在 debouncedSearch 函数的 if 条件中再添加一个条件即可。

    这是新功能

         const debouncedSearch = useCallback(_.debounce((params) => {
            if ((params.page && params.page === page) || (!params.page && page === 1)) {
                history.push({pathname: '/items', search: queryString.stringify(params)});
                fetchItems(params);
            } else {
                setPage(1);
            }
        }, 1000), []);
    

    但是,我仍然认为这不是正确的标准方式。所以,如果有人知道正确的方法,将不胜感激。

    【讨论】:

      猜你喜欢
      • 2021-08-16
      • 1970-01-01
      • 2019-03-01
      • 2020-03-19
      • 2018-05-15
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多