Поиск не работает с таблицей материалов React с использованием удаленных данных

Здесь я использую модуль таблицы материалов [1] с удаленными данными из веб-службы. Я включил параметр поиска, но он не работает, и в консоли нет сообщений об ошибках.

Вот код:

import React from 'react';
import ReactDOM from "react-dom";
import MaterialTable from 'material-table';


import { forwardRef } from 'react';

import AddBox from '@material-ui/icons/AddBox';
import ArrowUpward from '@material-ui/icons/ArrowUpward';
import Check from '@material-ui/icons/Check';
import ChevronLeft from '@material-ui/icons/ChevronLeft';
import ChevronRight from '@material-ui/icons/ChevronRight';
import Clear from '@material-ui/icons/Clear';
import DeleteOutline from '@material-ui/icons/DeleteOutline';
import Edit from '@material-ui/icons/Edit';
import FilterList from '@material-ui/icons/FilterList';
import FirstPage from '@material-ui/icons/FirstPage';
import LastPage from '@material-ui/icons/LastPage';
import Remove from '@material-ui/icons/Remove';
import SaveAlt from '@material-ui/icons/SaveAlt';
import Search from '@material-ui/icons/Search';
import ViewColumn from '@material-ui/icons/ViewColumn';

const tableIcons = {
    Add: forwardRef((props, ref) => <AddBox {...props} ref={ref} />),
    Check: forwardRef((props, ref) => <Check {...props} ref={ref} />),
    Clear: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
    Delete: forwardRef((props, ref) => <DeleteOutline {...props} ref={ref} />),
    DetailPanel: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
    Edit: forwardRef((props, ref) => <Edit {...props} ref={ref} />),
    Export: forwardRef((props, ref) => <SaveAlt {...props} ref={ref} />),
    Filter: forwardRef((props, ref) => <FilterList {...props} ref={ref} />),
    FirstPage: forwardRef((props, ref) => <FirstPage {...props} ref={ref} />),
    LastPage: forwardRef((props, ref) => <LastPage {...props} ref={ref} />),
    NextPage: forwardRef((props, ref) => <ChevronRight {...props} ref={ref} />),
    PreviousPage: forwardRef((props, ref) => <ChevronLeft {...props} ref={ref} />),
    ResetSearch: forwardRef((props, ref) => <Clear {...props} ref={ref} />),
    Search: forwardRef((props, ref) => <Search {...props} ref={ref} />),
    SortArrow: forwardRef((props, ref) => <ArrowUpward {...props} ref={ref} />),
    ThirdStateCheck: forwardRef((props, ref) => <Remove {...props} ref={ref} />),
    ViewColumn: forwardRef((props, ref) => <ViewColumn {...props} ref={ref} />)
};

const GET_PUBLICATIONS_URL = 'http://193.62.54.159/backend/v1/publications?';


class App extends React.Component {

    render() {
        return (
            <MaterialTable
                icons={tableIcons}
                title="Remote Data Preview"
                columns={[
                    { title: 'Publication ID', field: 'publicationId' },
                    { title: 'PMID', field: 'pmid' },
                    { title: 'First author', field: 'firstAuthor' },
                    { title: 'Publication', field: 'title' },
                    { title: 'Journal', field: 'journal' },
                    { title: 'Status', field: 'status' },
                ]}
                data={query =>
                    new Promise((resolve, reject) => {
                        // let url = 'https://reqres.in/api/users?'
                        let url = GET_PUBLICATIONS_URL
                        url += 'size=' + query.pageSize
                        url += '&page=' + (query.page)
                        fetch(url)
                            .then(response => response.json())
                            .then(result => {
                                resolve({
                                    data: result._embedded.publications,
                                    page: result.page.number,
                                    totalCount: result.page.totalElements,
                                })
                            })
                    })
                }
                options={{
                    search: true
                }}
            />
        )
    }
}

// export default DemoMUITable_RemoteData;
ReactDOM.render(<App />, document.getElementById("root"));

Вот пример выходных данных вызова веб-службы, использованного выше:

{
    _embedded: {
        publications: [{
                publicationId: "5d2dbec2483e4bcddc82c61c",
                pmid: "jqfWof0a6N",
                title: "hDoClFK1xW",
                journal: "bsmw70kDBz",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "VRbSDd72mC",
                    email: "YgH4UoELBp"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbec2483e4bcddc82c61c?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d2dbeff483e4bcddc82c61d",
                pmid: "WlQsCFYg3b",
                title: "bsthfcP7zY",
                journal: "sUULVFkYJQ",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "UOTBdYbsRh",
                    email: "ZUmHQ7evjl"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbeff483e4bcddc82c61d?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d2dbf05483e4bcddc82c61e",
                pmid: "V1KphgdwaG",
                title: "KoXVQJjoGp",
                journal: "1bO9QNNDCM",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "KsfpbpEAGc",
                    email: "p69YIXvYEq"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbf05483e4bcddc82c61e?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d2dbf0a483e4bcddc82c61f",
                pmid: "JEmARsAgWM",
                title: "CiOTlRIeD4",
                journal: "l1ofJObwtJ",
                firstAuthor: "NUed57buOd",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "rGdQGN5oPh",
                    email: "6PI3NfrnmV"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d2dbf0a483e4bcddc82c61f?pmid=false"
                    }
                }
            },
            {
                publicationId: "5d346e129bb39d8c6e33faa4",
                pmid: "cNUmFPonBy",
                title: "0LwQYP0fUK",
                journal: "C3gQOWPZ2C",
                firstAuthor: "q1LwUyYpgO",
                publicationDate: "2019-07-16T12:07:01.937Z",
                correspondingAuthor: {
                    authorName: "oJdt6ae7sp",
                    email: "jhdOF23b9m"
                },
                status: "ELIGIBLE",
                _links: {
                    self: {
                        href: "http://193.62.54.159/backend/v1/publications/5d346e129bb39d8c6e33faa4?pmid=false"
                    }
                }
            }
        ]
    },
    _links: {
        first: {
            href: "http://193.62.54.159/backend/v1/publications?page=0&size=5"
        },
        self: {
            href: "http://193.62.54.159/backend/v1/publications"
        },
        next: {
            href: "http://193.62.54.159/backend/v1/publications?page=1&size=5"
        },
        last: {
            href: "http://193.62.54.159/backend/v1/publications?page=5&size=5"
        }
    },
    page: {
        size: 5,
        totalElements: 26,
        totalPages: 6,
        number: 0
    }
}

Вот зависимости моего приложения:

"dependencies": {
    "@material-ui/icons": "^4.2.1",
    "material-table": "^1.40.1",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-scripts": "3.0.1"
  },

[1] https://github.com/mbrn/material-table


person tw1742    schedule 24.07.2019    source источник
comment
Кажется, отлично работает с опубликованным вами примером вывода. Вы можете проверить это здесь: wdre6.csb.app. Проблема, вероятно, кроется в ваших разрешенных данных.   -  person Isaac Pak    schedule 24.07.2019
comment
@IsaacPak Да, я вижу, что он там работает (wdre6.csb.app). У вас есть предложения, какие проблема могла быть в разрешенных данных, как отладить и решить проблему?   -  person tw1742    schedule 24.07.2019
comment
вы можете поиграть с ним здесь: codesandbox.io/s/search-remote-data- wdre6   -  person Isaac Pak    schedule 24.07.2019


Ответы (3)


Объект запроса содержит поле поиска, которое является текущим значением поиска. Вы должны передать это в свой онлайн-запрос и отфильтровать его в бэкэнде или отфильтровать во фронтенде следующим образом:

 resolve({
       data: result._embedded.publications.filter(pub => pub.firstAuthor.contains(query.search)),
       page: result.page.number,
       totalCount: result.page.totalElements,
 })

если вы фильтруете его во внешнем интерфейсе, вы должны написать свою настраиваемую функцию фильтра для фильтрации всех соответствующих полей, таких как имя, идентификатор и т. д.

person Domino987    schedule 24.07.2019
comment
Не уверен, что проблема в этом. Проверьте мою песочницу, она не требует свойства поиска. - person Isaac Pak; 24.07.2019
comment
поскольку он использует локальные данные, если он использует удаленные данные, фильтрация должна выполняться внутри серверной части - person Domino987; 24.07.2019
comment
@ Domino987 вы можете развернуть объект запроса, содержащий поле поиска? Означает ли это, что query.search предоставляется модулем? И я все еще привыкаю к ​​обозначению стрелок, где мне добавить вызов функции настраиваемого фильтра? - person tw1742; 24.07.2019
comment
да query.search - это текст в поле поиска. Добавьте это в качестве параметра к URL-адресу, например: url + = '& search =' + (query.search), извлеките это в своем бэкэнде и верните только отфильтрованные данные в вызов API - person Domino987; 24.07.2019
comment
Спасибо, в этом есть смысл. Банкомат, у меня нет этого параметра в бэкэнд-вызове. Вы предлагаете, чтобы для масштабируемости лучше, чтобы веб-служба выполняла фильтрацию? - person tw1742; 24.07.2019
comment
material-table уже содержит фильтры. Такая внутренняя оптимизация, вероятно, имеет смысл при работе с большими наборами данных. - person Isaac Pak; 24.07.2019
comment
Это зависит от того, если у вас много публикаций, будет лучше загружать только те, которые вы сейчас показываете. Если вам все равно нужно иметь их локально, просто передайте их из родительских реквизитов в опору данных, если таблица и все будут работать нормально. Но если это единственное место, да, будет лучше отфильтровать их в Backend - person Domino987; 24.07.2019
comment
@Isaac Pak фильтрация не работает для удаленных данных - person Domino987; 24.07.2019
comment
Я оцениваю в списке 5-10 тысяч публикаций. Пользователи должны выполнить фильтрацию по PMID, и будет возвращена 1 публикация. @ Domino987 у вас есть пример того, как можно настроить фильтрацию внешнего интерфейса? Я всего несколько недель в React и все еще много разбираюсь :) - person tw1742; 24.07.2019
comment
Как это происходит в случае возврата данных после API выборки: data: result._embedded.publications.filter (pub = ›pub.firstAuthor.contains (query.search)). Вы можете изменить этого первого автора на то, что вам нужно отфильтровать - person Domino987; 24.07.2019
comment
О, я вижу. Раньше у меня была ошибка, и я подумал, что нужно больше. Мне нужно было использовать inlcudes для моего объекта данных, например. data: result._embedded.publications.filter(pub => pub.pmid.includes(query.search) || pub.firstAuthor.includes(query.search)) Однако это фильтрует только строки, доступные для просмотра в данный момент. - person tw1742; 24.07.2019
comment
Потому что это публикации, которые вы получаете при вызове функции. Это только один раз, показанный в настоящее время без фильтра, но он не обязательно должен соответствовать отфильтрованным данным. Вот почему была бы полезна фильтрация в Backend. - person Domino987; 25.07.2019

Для всех, кто пришел сюда в поисках решения, как выполнять поиск на сервере в таблице материалов с помощью крючков.

Произошла ошибка (https://github.com/mbrn/material-table/pull/1611, что нарушало поле поиска, поэтому убедитесь, что у него есть [email protected].

codeandbox.io/ s / material-table-server-search-on-hooks-tnniz.

import React, { useEffect, useState } from "react";
import MaterialTable from "material-table";
import useAxios from "axios-hooks";

const MaterialTableSearchDemo = () => {
  const [query, setQuery] = useState("");
  const [items, setItems] = useState([]);
  const [{ data = {}, loading }, runSearch] = useAxios(
    `https://api.github.com/search/repositories?q=${query}&sort=stars&order=desc&type=Repositories`,
    { manual: true }
  );

  const columns = [
    { title: "Name", field: "name" },
    { title: "Stars", field: "stargazers_count" }
  ];

  useEffect(() => {
    if (query) {
      runSearch();
    } else {
      setItems([]);
    }
  }, [query, runSearch]);

  useEffect(() => {
    if (!loading && Array.isArray(data.items)) {
      setItems(data.items);
    }
  }, [loading, setItems, data.items]);

  return (
    <MaterialTable
      title="Github repositories"
      data={items}
      columns={columns}
      onSearchChange={setQuery}
      options={{
        debounceInterval: 500,
        paging: false,
        //searchAutoFocus: true
      }}
      localization={{
        toolbar: {
          searchPlaceholder: "e.g. React"
        }
      }}
      isLoading={loading}
    />
  );
};

export default MaterialTableSearchDemo;
person keemor    schedule 10.06.2020

Если вы хотите выполнить поиск во всех строках и столбцах таблицы, вы можете использовать следующую функцию.

resolve({
           data: result._embedded.publications.filter(function(obj) {
          return Object.keys(obj).some(function(key) {
            return obj[key] ? (obj[key]).toString().includes(query.search) : false;
          })
        }),
           page: result.page.number,
           totalCount: result.page.totalElements,
     })

remoteSearch=(arr, searchKey)=>{
    return arr.filter(function(obj) {
      return Object.keys(obj).some(function(key) {
        return obj[key] ? (obj[key]).toString().includes(searchKey) : false;
      })
    });
  }
  
  
  console.log(remoteSearch([{a:1},{b:"1"},{c:"test1"}],1))

person Soheil Jafarzade    schedule 07.07.2020