如何在 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)} />
);

这提供了所需的结果。