Categories
程式開發

用React Hooks做一個搜索欄


本文最初發佈於 Hackernoon 博客,經原作者授權由 InfoQ 中文站翻譯並分享。

以下是我們將要構建的搜索框的動圖。這是一個簡單的搜索框,我們可以用它來搜索聯繫人列表。我們將使用函數式組件,而不是基於類的組件來實現它。

用React Hooks做一個搜索欄 1

下面就開始吧。首先創建一個新的 React 應用:

npx create-react-app contacts-list 

然後轉到 contacts-list 目錄。在你常用的代碼編輯器中打開目錄。就我而言,我使用的是 vscode,因此我要從命令行執行的操作是:

code .

src 目錄中創建一個名為 components 的新文件夾,並在其中創建一個 Numbers.js 文件。轉到你的 App.js 文件並導入 Numbers.js 組件。

接下來我們需要創建一些人名,然後將這些人名作為 props 傳遞給 Numbers.js 組件來渲染。

import React, { useState } from "react";
import { Numbers } from "./components/Numbers";
export const App = () => {
  const [persons] = useState([
    { name: "Dayo Olorinla", number: "+234-1234-5678" },
    { name: "Temi Otedola", number: "+234-9029-9229" },
    { name: "Zlatan Ibile", number: "+234-1243-2345" },
  ]);

  return (
    
); }; export default App;

現在在我們的 Numbers 組件中,我們將接收從 App 傳遞過來的 props,並使用它來顯示 contacts list

參見下面的代碼,其中包含每個步驟的解釋說明。

import Rect, { useStae } from "react";
export const Numbers = props => {
// word 会跟踪 filter box 内输入的任何更改
  const [word, setword] = useState("");
// filterdisplay 会基于 search 来显示更新的列表,其默认状态是我们的 persons 列表 prop
  const [filterDispllay, setFilterDisplay] = useStae(props.persons);
// handleChange 每次运行时在输入字段都会有一个更改
  const handleChange = e => {
// 在一个新数组中存放原始列表,将所有人名转为小写字母,因为我们不知道用户要输入什么格式;然后我们返回 OldList 作为一个对象数组,来存放这个更改的列表
  let oldList = props.persons.map(person => {
    return { name: person.name.toLowerCase(), number: person.number };
  });
  // 如果输入栏不为空,则运行以下代码;否则,setFilterDisplay 设为原始列表 prop
  if (e !== "") {
    let newList =[];
    // setWord 一直跟踪输入的任何更改
    setWord(e);
    // newList 是保存符合搜索参数的 persons 的数组
    newList = oldList.filter(person =>
// 我们调用 includes 方法并用小写传递进'word'状态,这会检查 oldList 是否包含名字中带有'word'的人名
      person.name.includes(word.toLowerCase())
    );
// 我们会一直检查输入并返回 newList 数组。我们调用 setFilterDisplay 来在每次输入调整后更新状态
      setFilterDisplay(newList);
    }
  };
  return (
    
Number filter: handleChange(e.target.value)} /> {filterDisplay.map((person, i) => (
  • {person.name} {person.number}
  • ))}
    ); };

    最後,每次更新時,我們都會從 FilterDisplay 返回更新的信息。如果你和我一樣想將搜索欄分成一個單獨的組件,請繼續看下去。下面我們來重構這個東西!將搜索拆分成一個單獨的組件後,我們就可以在應用程序的其他組件中使用同樣的搜索欄了。

    首先我們創建一個 Filter 組件,在我們的 components 文件夾中將其命名為 Filter.js。它需要 2 個 props,分別用於輸入值和 onChange 事件。

    import React from "react";
    export const Filter = ({ value, handleChange }) => {
      return (
        
    filter:
    ); };

    接下來我們需要重構 Numbers.js 組件,讓它只渲染過濾過的人員列表。它將接受一個 prop,也就是 list/array。

    import React from "react";
    export const Numbers = ({ persons }) => {
      return (
        
    Numbers {person.map((person, i) => (
  • {person.name} {person.number}
  • ))}
    ); };

    回想一下,我們所有的狀態都在 App 組件內管理,並作為 props 傳遞給我們的組件。最後,在 App 組件中我們將一個有狀態值傳遞給 Filter 組件中的輸入字段,還將傳遞一個 handleChange 方法,當輸入字段中發生更改時將調用這個方法。

    import React, { useState } from "react";
    import { Filter } from "./components/Filter";
    import { Numbers } from "./components/Numbers";
    export const App = () => {
      const [word, setWord] = useState("");
      const [persons] = useState([
        { name: "Dayo Olorinla", number: "+234-1244-5678" },
        { name: "Temi Otedola", number: "+234-9029-9229" },
        { name: "Zlatan Ibile", number: "+234-1243-2345" }
      ]);
      const [filterDisplay, setFilterDisplay] = useState([]);
    
      const handleChange = e => {
        setWord(e);
        let oldList = persons.map(person => {
          return { name: person.name.toLowerCase(), number: person.number };
        });
    
        if (word !== "") {
          let newList = [];
    
          newList = oldList.filter(person =>
            person.name.includes(word.toLowerCase())
          );
    
          setFilterDisplay(newList);
        } else {
          setFilterDisplay(persons);
        }
      };
    
      return (
        
    handleChange(e.target.value)} /> ); }; export default App;

    return 中,我們的 Numbers 組件將始終檢查輸入字段是否為空白。如果是的話就渲染原始的 Persons 數組,否則我們根據在輸入字段中輸入的內容渲染列表。就是這樣,搞定!

    英文原文

    How to Build a Search Bar in React With React Hooks