如何在 React.js 应用程序上使用多个用户输入来过滤 table
How to filter a table using multiple user inputs on a React.js app
我在 React 应用程序上有 2 个主要组件:一个是带有一堆数据的 table(使用 Rsuite Table),另一个在 table 之上,只是具有多个 input
文本字段的 div
。就这么简单:
例如,如果用户在 'firstName' 输入字段中键入 T 字母,则 table 网格应立即仅显示名称名称中包含 T。这很好,我的实际问题是如何为您在上图中看到的 3 个输入实现这一点。也就是说,如果用户在多个输入文本框中输入内容?往下看:
这是我的主要 App.js
的样子:
function App() {
const [dummyData, setDummyData] = useState([]);
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [city, setCity] = useState('');
const firstNameHandler = (input) => {
setFirstName(input);
}
const lasttNameHandler = (input) => {
setLastName(input);
}
const firstNameHandler = (input) => {
setCity(input);
}
useEffect(() => {
const generateRandomData = () => {
setDummyData([...Array(100).keys().map(key => {
return {
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
city: faker.address.city()
}
})
)}
generateRandomData();
}, []);
return(
<Filters changeFirstName={firstNameHandler} changeLastName={lastNameHandler} changeCity={cityHandler}/>
<InfoTable items={dummyData}/>
);
}
export default App;
PS: 正在从 Filters
组件中提升状态。我使用 useEffect
在组件首次加载时生成随机数据。 dummyData 传递给 InfoTable
只是一个数组,其中包含使用 faker.js 随机生成的对象,它们看起来像这样:
{
firstName: "John",
lastName: "Smith",
city: "San Francisco"
}
我的 Filters.js
组件如下所示:
function Filters = (props) => {
const firstNameInputHandler = (event) => {
props.changeFirstName(event.target.value);
}
const lastNameInputHandler = (event) => {
props.changeLastName(event.target.value);
}
const cityInputHandler = (event) => {
props.changeCity(event.target.value);
}
return(
<div className="user_inputs">
<label htmlFor="firstName">First Name:</label>
<input id="firstName" type="text" onChange={firstNameInputHandler}/>
</div>
<div className="user_inputs">
<label htmlFor="lastName">Last Name:</label>
<input id="lastName" type="text" onChange={lastNameInputHandler}/>
</div>
<div className="user_inputs">
<label htmlFor="city">City:</label>
<input id="city" type="text" onChange={cityInputHandler}/>
</div>
);
}
export default Filters;
所以如您所见,我正在提升状态,所以我可以在 App.js
上使用它们,这样我就可以过滤我传递给 table 道具的数组。
我的 InfoTable.js
组件非常简单,看起来像这样,再次使用 Rsuite Table:
function InfoTable = (props) => {
return(
<Table virtualized height={500} data={props.items} rowHeight={30}>
<Column width={60}>
<HeaderCell>First Name</HeaderCell>
<Cell dataKey="firstName"/>
</Column>
<Column width={60}>
<HeaderCell>Last Name</HeaderCell>
<Cell dataKey="lastName"/>
</Column>
<Column width={60}>
<HeaderCell>City</HeaderCell>
<Cell dataKey="city"/>
</Column>
</Table>
);
}
export default InfoTable;
table 显示确实很好,但我想要的是根据用户可能输入或不输入的各种文本字段过滤数据。例如:如果用户在名字输入字段中键入 Jo,在姓氏输入字段中键入 S,我想要 table 以仅显示符合此条件的对象。然后,如果用户键入 California,我希望 table 重新调整为仅来自加利福尼亚的名字包含 Jo[=74= 的人] 和包含 S 的姓氏。如果用户删除所有内容,table 应该是原来的 100 个值。
我认为问题的一小部分是,在 App.js
我检查 firstName 状态长度是否大于 0,如果是,我 运行 .filter
我作为道具传递的数组。所以在 return 中,关于网格组件,我有条件地将它渲染为 suck:
return(
bla bla bla (...)
{firstName.length === 0 && <InfoTable items={dummyData} />
{firstName.length > 0 && <InfoTable items={dummyData.filter((obj) => {
return obj.firstName.includes(firstName)})
}
);
我可以 'kind of' 使用这种方法来检查字段中是否有输入,并使用 100 行或按该条件过滤来呈现 table。问题是,我如何使这 3 个输入起作用?
例如:如果用户在 First Name 输入字段中键入 Jo,并且在 [=] 中键入 S 56=]Last Name 输入字段,我希望 table 仅显示符合此条件的行(名字包含 Jo 和姓氏的对象包括 S)。然后,如果用户在 City 字段中键入加利福尼亚,我希望 table 重新调整为仅来自加利福尼亚的名字包含 Jo 的人 和包含 S 的姓氏。如果用户从所有 3 个输入中删除文本,table 应该重新调整以显示原始的 100 个值。
请帮忙。
对不起,我没有足够的声誉来发表评论,所以我回答这个问题
如果这是一个演示,或者数据量很小,我认为 filter
完全可以,只需简单地链接过滤器即可:
const newData = originalData.filter(condition1).filter(condition2).filter(condition3)
如果这是一个高效的 Web 应用程序,也许我们应该让后端的 API 做有关过滤器的事情,因为数据可能很大并且可能依赖于某种搜索引擎
如果你真的只想在客户端做,而且数据可能也很大,应该有一些技术,比如搜索引擎,只用于客户端,但我没有这方面的经验
考虑到给出的示例,解决方案非常简单明了:
const filterCriteria = (obj) => {
return obj.firstName.includes(firstName)
&& obj.lastName.includes(lastName)
&& obj.city.includes(city);
}
return(
<InfoTable items={dummyData.filter(filterCriteria)} />
);
这提供了所需的结果。
我在 React 应用程序上有 2 个主要组件:一个是带有一堆数据的 table(使用 Rsuite Table),另一个在 table 之上,只是具有多个 input
文本字段的 div
。就这么简单:
例如,如果用户在 'firstName' 输入字段中键入 T 字母,则 table 网格应立即仅显示名称名称中包含 T。这很好,我的实际问题是如何为您在上图中看到的 3 个输入实现这一点。也就是说,如果用户在多个输入文本框中输入内容?往下看:
这是我的主要 App.js
的样子:
function App() {
const [dummyData, setDummyData] = useState([]);
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [city, setCity] = useState('');
const firstNameHandler = (input) => {
setFirstName(input);
}
const lasttNameHandler = (input) => {
setLastName(input);
}
const firstNameHandler = (input) => {
setCity(input);
}
useEffect(() => {
const generateRandomData = () => {
setDummyData([...Array(100).keys().map(key => {
return {
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
city: faker.address.city()
}
})
)}
generateRandomData();
}, []);
return(
<Filters changeFirstName={firstNameHandler} changeLastName={lastNameHandler} changeCity={cityHandler}/>
<InfoTable items={dummyData}/>
);
}
export default App;
PS: 正在从 Filters
组件中提升状态。我使用 useEffect
在组件首次加载时生成随机数据。 dummyData 传递给 InfoTable
只是一个数组,其中包含使用 faker.js 随机生成的对象,它们看起来像这样:
{
firstName: "John",
lastName: "Smith",
city: "San Francisco"
}
我的 Filters.js
组件如下所示:
function Filters = (props) => {
const firstNameInputHandler = (event) => {
props.changeFirstName(event.target.value);
}
const lastNameInputHandler = (event) => {
props.changeLastName(event.target.value);
}
const cityInputHandler = (event) => {
props.changeCity(event.target.value);
}
return(
<div className="user_inputs">
<label htmlFor="firstName">First Name:</label>
<input id="firstName" type="text" onChange={firstNameInputHandler}/>
</div>
<div className="user_inputs">
<label htmlFor="lastName">Last Name:</label>
<input id="lastName" type="text" onChange={lastNameInputHandler}/>
</div>
<div className="user_inputs">
<label htmlFor="city">City:</label>
<input id="city" type="text" onChange={cityInputHandler}/>
</div>
);
}
export default Filters;
所以如您所见,我正在提升状态,所以我可以在 App.js
上使用它们,这样我就可以过滤我传递给 table 道具的数组。
我的 InfoTable.js
组件非常简单,看起来像这样,再次使用 Rsuite Table:
function InfoTable = (props) => {
return(
<Table virtualized height={500} data={props.items} rowHeight={30}>
<Column width={60}>
<HeaderCell>First Name</HeaderCell>
<Cell dataKey="firstName"/>
</Column>
<Column width={60}>
<HeaderCell>Last Name</HeaderCell>
<Cell dataKey="lastName"/>
</Column>
<Column width={60}>
<HeaderCell>City</HeaderCell>
<Cell dataKey="city"/>
</Column>
</Table>
);
}
export default InfoTable;
table 显示确实很好,但我想要的是根据用户可能输入或不输入的各种文本字段过滤数据。例如:如果用户在名字输入字段中键入 Jo,在姓氏输入字段中键入 S,我想要 table 以仅显示符合此条件的对象。然后,如果用户键入 California,我希望 table 重新调整为仅来自加利福尼亚的名字包含 Jo[=74= 的人] 和包含 S 的姓氏。如果用户删除所有内容,table 应该是原来的 100 个值。
我认为问题的一小部分是,在 App.js
我检查 firstName 状态长度是否大于 0,如果是,我 运行 .filter
我作为道具传递的数组。所以在 return 中,关于网格组件,我有条件地将它渲染为 suck:
return(
bla bla bla (...)
{firstName.length === 0 && <InfoTable items={dummyData} />
{firstName.length > 0 && <InfoTable items={dummyData.filter((obj) => {
return obj.firstName.includes(firstName)})
}
);
我可以 'kind of' 使用这种方法来检查字段中是否有输入,并使用 100 行或按该条件过滤来呈现 table。问题是,我如何使这 3 个输入起作用? 例如:如果用户在 First Name 输入字段中键入 Jo,并且在 [=] 中键入 S 56=]Last Name 输入字段,我希望 table 仅显示符合此条件的行(名字包含 Jo 和姓氏的对象包括 S)。然后,如果用户在 City 字段中键入加利福尼亚,我希望 table 重新调整为仅来自加利福尼亚的名字包含 Jo 的人 和包含 S 的姓氏。如果用户从所有 3 个输入中删除文本,table 应该重新调整以显示原始的 100 个值。
请帮忙。
对不起,我没有足够的声誉来发表评论,所以我回答这个问题
如果这是一个演示,或者数据量很小,我认为 filter
完全可以,只需简单地链接过滤器即可:
const newData = originalData.filter(condition1).filter(condition2).filter(condition3)
如果这是一个高效的 Web 应用程序,也许我们应该让后端的 API 做有关过滤器的事情,因为数据可能很大并且可能依赖于某种搜索引擎
如果你真的只想在客户端做,而且数据可能也很大,应该有一些技术,比如搜索引擎,只用于客户端,但我没有这方面的经验
考虑到给出的示例,解决方案非常简单明了:
const filterCriteria = (obj) => {
return obj.firstName.includes(firstName)
&& obj.lastName.includes(lastName)
&& obj.city.includes(city);
}
return(
<InfoTable items={dummyData.filter(filterCriteria)} />
);
这提供了所需的结果。