react创建自定义组件
我将向大家展示如何制作一个基本的搜索引擎,使任何人都可以搜索特定的 使用React中的任何包或库构建的表中的数据。
此方法是一种通用方法,适用于涉及向表中馈送数据源以呈现行的任何类型的表。
随着事情开始变得越来越艰难,我们将开始进行缓慢的解释,并且我们开始构建自己的小型搜索引擎,因此,请随时查看以下实现了整个过程的沙箱:
阅读整个故事,因为我将深入讨论所有代码和涉及的自定义钩子。
使用哪个库来构建表都没有关系。 我将使用antd,这是一个React库,用于 设计涉及表单控制和大型表的复杂接口。 对于数据,我使用了https://jsonplaceholder.typicode.com/users中的用户。 您可以在遍历代码时查看数据,以便更好地理解内容。
让我们开始吧。
文件结构如下:

index.js只是呈现App组件。 我将经历 应用组件优先:
import React, { useState } from "react" ;
import { Table, Input } from "antd" ;
import axios from "axios" ;
import { userColumns } from "./columns" ;
import { useTableSearch } from "./useTableSearch" ;
const { Search } = Input
在这里, axios将帮助我们从jsonplaceholder的用户API中获取数据。 userColumns是我们将在用户表中使用的列。 您可以在沙箱中自行检查它们。 useTableSearch是一个自定义钩子,根据我们的搜索查询,我们将使用它来过滤数据。
const fetchUsers = async () => {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/users/"
);
return { data };
};这是fetchUsers函数,我们将其传递给钩子,以便它可以获取所有用户的数据,然后将这些数据用作fetchUsers搜索的数据。
export default function App () {
const [searchVal, setSearchVal] = useState( null );
const { filteredData, loading } = useTableSearch({
searchVal,
retrieve : fetchUsers
});
这是我们的App组件的主体。 首先,我们将定义我们的本地状态。 searchVal将保留来自搜索栏的用户输入的值,而setSearchVal将帮助我们在要附加到搜索栏元素的onChange事件处理程序中更新其值。 我们将其初始值设置为null 。
下一行显示了我们将如何利用useTableSearch自定义钩子来基于searchVal获得过滤后的数据。 我们将传递前面提到的searchVal和fetchUsers函数作为retrieve参数,该参数将用于在挂钩中获取数据,以便searchVal可以用于过滤该数据。 挂钩将返回filteredData以及一个loading参数,该参数可用于在首次获取数据时显示微调框。
return (
<>
<Search
onChange={e => setSearchVal(e.target.value)}
placeholder="Search"
enterButton
style={{position: 'sticky', top: '0', left: '0'}}
/>
<br /> <br />
<Table
dataSource={filteredData}
columns={userColumns}
loading={loading}
pagination={false}
rowKey='name'
/>
</>
);
}我将使用antd Search组件来呈现搜索栏,您可以使用任何类型的文本输入来执行相同的操作。 每当用户键入内容时, onChange函数都会更新searchVal状态变量的值。 这将导致整个组件的重新呈现,并且将更新后的searchVal传递到我们的自定义钩子,该钩子反过来返回filteredData 。 然后将其作为dataSource传递到我们的表中。
到目前为止,您已经可以继续进行,并开始在个人项目中使用该挂钩。 现在,我将详细介绍搜索引擎的工作原理。 因此,如果您有兴趣了解东西的工作原理,请继续阅读!
风俗钩
React中自定义钩子的美丽在于它的可重用性和易用性。 我个人正在从事一个包含大量表的项目。 该挂钩对于将所有表添加相同的功能非常有用。
让我们看一下代码
import { useState, useEffect } from "react" ;
export const useTableSearch = ( { searchVal, retrieve } ) => {
const [filteredData, setFilteredData] = useState([]);
const [origData, setOrigData] = useState([]);
const [searchIndex, setSearchIndex] = useState([]);
const [loading, setLoading] = useState( true );首先,我们将定义状态。 filteredData是一个过滤对象数组, origData是我们将使用从App组件传递到钩子的retrieve方法获取的原始数据, searchIndex是我们将使用origData构建的搜索索引。 每当searchVal更改时,此searchIndex将用于过滤数据。 最后,我们将进行loading ,告诉我们何时获取数据。
useEffect(() => {
setLoading( true );
const crawl = ( user, allValues ) => {
if (!allValues) allValues = [];
for ( var key in user) {
if ( typeof user[key] === "object" ) crawl(user[key], allValues);
else allValues.push(user[key] + " " );
}
return allValues;
};
const fetchData = async () => {
const { data : users } = await retrieve();
setOrigData(users);
setFilteredData(users);
const searchInd = users.map( user => {
const allValues = crawl(user);
return { allValues : allValues.toString() };
});
setSearchIndex(searchInd);
if (users) setLoading( false );
};
fetchData();
}, [retrieve]);这是我们的第一个useEffect调用,它执行2个主要任务:
- 要获取原始
users数据并将其存储在我们的本地状态。 - 使用数据生成搜索索引,以后可将其用于执行实际过滤,并将其存储在我们的本地状态中。
仅当retrieve功能更改时才调用它。 因此,大多数情况下,只有在安装组件时才调用一次。
现在,什么是搜索索引? 用外行的术语来说,搜索索引是我们要在其上执行搜索的原始数据的一种修改形式,这样该修改使搜索操作更容易/更可行。 那么,我们如何修改users数据,从而可以在数据上搜索值? 实际上,我可以使用的一种简单方法是对我们的users对象数组中存在的每个user所有值进行爬网(或迭代),并将每个user对象转换为单个字符串。 这将使我们能够使用JavaScript中的indexOf()函数基于searchVal过滤数据,因为如果传递给它的字符串是子字符串,则indexOf()函数将返回一个正整数(即子字符串的索引) -给定字符串的字符串,否则为-1。 让我们深入。
爬行者
首先要记住的是,对users数组中存在的每个user对象都调用了爬网函数,并返回该对象的所有值的数组。 稍后,我们使用toString()函数将该数组转换为单个字符串,该函数将allValues数组中存在的所有值连接在一起。 这是使用一个简单的递归函数完成的,该函数根据每个键的值检查是否需要进一步爬网,下面举一个例子:

搜寻器将从id开始并将其推送到allValues数组。 它将继续推送值,直到遇到address键为止,在这种情况下,它需要进一步爬入以获取值,它将做到这一点。 将为address对象递归调用爬网函数,并且所有address值都allValues入allValues 。
最后,我们将得到一个包含所有user值的数组,我们将使用toString()将其转换为字符串。 这将为所有users ,并将共同构成我们的searchIndex 。
现在,在fetchData函数中,我们使用了从App组件传递来的retrieve参数来提取所有users 。 之后,我们通过映射所有users并在其中每个users进行爬网来生成searchIndex 。 在开始获取数据之前,请确保将setLoading为true然后在获取数据后将其设置为false 。
现在我们有了searchIndex ,让我们searchIndex一下过滤部分。
useEffect(() => {
if (searchVal) {
const reqData = searchIndex.map( ( user, index ) => {
if (user.allValues.toLowerCase().indexOf(searchVal.toLowerCase()) >= 0 )
return origData[index];
return null ;
});
setFilteredData(
reqData.filter( user => {
if (user) return true ;
return false ;
})
);
} else setFilteredData(origData);
}, [searchVal, origData, searchIndex]);
return { filteredData, loading };
};注意,我们将searchVal作为钩子的依赖项。 每次用户输入更改时,都会调用此挂钩。
我们映射到searchIndex存在的所有字符串。 searchIndex每个字符串searchIndex对应于origData中存在的原始user ,该user与该字符串具有相同的index 。 因此,通过indexOf()函数,如果我们发现searchVal是substring在说一个当前字符串- index=5我们的searchIndex ,我们可以说, user目前在index=5我们的origData应该是一个一部分的filteredData 。
这就是进行过滤的方式。 如果searchVal不是searchIndex字符串的substring字符串,则对于相应的index值返回null 。 最后,我们过滤数据以删除所有这些null值,然后在本地状态下将filteredData设置为更新后的值。 这就是与loading一起返回给App组件的内容。
结论
我们在React中使用了一个自定义钩子来使用搜索查询过滤数据,然后使用过滤后的数据来呈现我们的表。 在筛选数据的过程中,我们制作了一个小型对象搜寻器和一个搜索索引来帮助我们进行此过程。
这就是您可以为表构建搜索引擎的方式。 这就是我现在所拥有的。 我希望你们喜欢这个解释。 谢谢阅读! 上帝的速度。
翻译自: https://hackernoon.com/how-to-create-a-search-engine-for-any-table-using-a-custom-react-hook-gxm3u21
react创建自定义组件