首页 > 解决方案 > 从父文本框中搜索子组件的功能

问题描述

我有一个 SideBar 组件,它有一个名为 SideBarLink 的子组件,它指向正确的页面。

我正在尝试使用文本字段将搜索功能添加到我的侧边栏。

我已经向 SideBar 组件添加了一个文本输入,并且我试图根据搜索文本和 SideBarLink 的 text 属性之间的匹配找出隐藏 SideBarLink 组件的最佳方法。

这是我当前对侧边栏的设计,但是当我们已经知道 text 属性时(尤其是当我开始添加更多链接时),在每个 SideBarLink 上声明隐藏事件感觉很难看。

import "./SideBar.css";
import React, { useState } from "react";
import SideBarDropdown from "./SideBarDropdown";
import SideBarLink from "./SideBarLink";
import { TextInput } from "../Input";

const SideBar: React.FC = () => {
  const [searchPhrase, setSearchPhrase] = useState<string>();

  const acroynym = (str: string) =>
    str
      .split(/\s/)
      .reduce((response, word) => (response += word.slice(0, 1)), "");

  const match = (text: string) =>
    searchPhrase
      ? text.toLowerCase().includes(searchPhrase?.toLowerCase()) ||
        acroynym(text).toLowerCase().includes(searchPhrase?.toLowerCase())
      : true;

  return (
    <nav id="sidebar" className="custom_scrollbar">
      <ul className="list-unstyled components">
        <TextInput
          value={searchPhrase}
          onChange={(value: string) => setSearchPhrase(value!)}
        />
          <SideBarLink
            to={`${urls.accounts}`}
            text="Account"
            icon="fas fa-plus-square"
            hidden={!match("Account")}
          />
          <SideBarLink
            to={`${urls.customers}`}
            text="Customer"
            icon="fas fa-plus-square"
            hidden={!match("Customer")}
          />
          <SideBarLink
            to={`${urls.orders}`}
            text="Order"
            icon="fas fa-plus-square"
            hidden={!match("Order")}
          />
      </ul>
    </nav>
  );
};

export default SideBar;

这是更新所有子组件的最佳方法吗?

标签: javascriptreactjstypescript

解决方案


如果您想要一种快速而肮脏的方式,只需将搜索文本传递给 SideBarLink 并在那里声明您的 isMatch 函数(您还应该考虑记住您的函数,这样它就不会在每次渲染后重新声明)

但我不喜欢这种方法,因为您的 SideBarLink 是否显示与 SideBarLink 本身无关。它是侧边栏组件中呈现逻辑的一部分,因此它应该保留在那里。为了做到这一点,只需在数组中定义所有链接并映射它。像这样:

const links = useMemo(() => [
    { text: 'Account', to: `${urls.accounts}`, icon: 'fas fa-plus-square' },
    { text: 'Customer', to: `${urls.customers}`, icon: 'fas fa-plus-square' },
  ], []);

然后在数组上的渲染循环中:

   {links.map(({ text, to, icon }) => (
    <SideBarLink
      text="Customer"
      to={`${urls.customers}`}
      icon="fas fa-plus-square"
      isMatch={isMatch(text)}
    />
  ))}

也不要忘记记住你的 isMatch 函数:

 const isMatch = useCallback(
    (text: string) =>
      searchPhrase
        ? text.toLowerCase().includes(searchPhrase?.toLowerCase()) ||
          acroynym(text).toLowerCase().includes(searchPhrase?.toLowerCase())
        : true,
    [searchPhrase],
  );

推荐阅读