React – Crear campo de búsqueda en tiempo real

App search
App search

Hola a todos, hoy voy a explicar como programar un campo de búsqueda en tiempo real en una página de react.

Es un recurso que siempre se necesita en una web y sobre todo cuando estás mostrando información desde un estado o una variable con array.

Primeros pasos

Lo primero de todo es tener un proyecto creado con React ya que me estoy enfocando en esta librería, aunque con modificaciones podría funcionar en una aplicación JavaScript pura o en otros tipos de proyectos.

   
   npx create-react-app search

Una vez creado el proyecto, yo he borrado lo que no era necesario para dejarlo vacío.

También he instalado bootstrap para ayudarme con los estilos.

   
   npm install bootstrap

Dentro del proyecto yo he creado un archivo llamado users.js donde dispongo de un array con los datos de usuario que voy a utilizar aunque también puedes crear un array dentro del mismo archivo js que estés modificando.

Este es el fichero users.js que he creado:

   const users = [
        {
            "id": 1,
            "dept": "Digital Strategist",
            "name": "Mark Thompson",
            "phone": "+ 800 - 12 12 23 52"
        },
        {
            "id": 2,
            "dept": "Developer",
            "name": "Nicole Pearson",
            "phone": "+ 800 - 12 12 23 52"
        },
        {
            "id": 3,
            "dept": "Comercial",
            "name": "Diana Tail",
            "phone": "+ 800 - 12 12 23 52"
        },
        {
            "id": 4,
            "dept": "Boss",
            "name": "Emily Tomas",
            "phone": "+ 800 - 12 12 23 52"
        }
]

Programación App.js

Yo voy a utilizar el App.js como archivo donde voy a mostrar los usuarios y realizar la búsqueda en tiempo real de los nombres de dichos usuarios para que solo me salgan los usuarios que contengan las letras que voy insertando en Input de texto de búsqueda sin pulsar ningún botón.

Mi archivo vacio de App.js seria de la siguiente forma:

import './App.css';


function App() {

  return (
    <>
      
    </>
  );
}

export default App;

Primero tenemos que importar el archivo de usuarios y lo asignaremos a una variable. También importaremos bootstrap y crearemos un div con la clase «container» para que se justifique a la página con márgenes

import './App.css';
import users from './users';
import "../node_modules/bootstrap/dist/css/bootstrap.min.css"

function App() {


  const allusers = users;

  return (
    <>
      <div className='container'> 
      </div>
    </>
  );
}

export default App;

En el siguiente paso crearemos la estructura en la que vamos a mostrar los datos. En este caso voy a crear un Input para hacer la búsqueda y una tabla con su parte head y su parte body que estará vacía ya que es donde vamos a insertar los datos.

Para hacerlo más bonito utilizaré unas clases de bootstrap: «form-control» para el Input y «table» junto a «table-striped» para darle la forma a la tabla donde voy a mostrar los datos.

import './App.css';
import users from './users';
import "../node_modules/bootstrap/dist/css/bootstrap.min.css"

function App() {


  const allusers = users;

  return (
    <>
      <div className='container'>
        <h1>Usuarios</h1>
        <input className="form-control" type="text" placeholder="Search" />
        <table className="table table-striped">
          <thead>
            <tr>
              <td>ID</td>
              <td>Name</td>
              <td>Departmet</td>
              <td>Phone</td>
            </tr>
          </thead>
          <tbody>
           
          </tbody>
        </table>
      </div>
    </>
  );
}

export default App;

El siguiente paso es mostrar los datos de los usuarios en la tabla por lo que utilizaremos la propiedad «map» para que me vaya creando una fila con sus celdas por cada usuario que disponemos en la variable.

import './App.css';
import users from './users';
import { useState } from "react"
import "../node_modules/bootstrap/dist/css/bootstrap.min.css"

function App() {


  const allusers = users;

  return (
    <>
      <div className='container'>
        <h1>Usuarios</h1>
        <input className="form-control" type="text" placeholder="Search" />
        <table className="table table-striped">
          <thead>
            <tr>
              <td>ID</td>
              <td>Name</td>
              <td>Departmet</td>
              <td>Phone</td>
            </tr>
          </thead>
          <tbody>
            {
              allusers.map(user => {
                return (
                  <tr>
                    <td>{user.id}</td>
                    <td>{user.name}</td>
                    <td>{user.dept}</td>
                    <td>{user.phone}</td>
                  </tr>
                )
              })
            }
          </tbody>
        </table>
      </div>
    </>
  );
}

export default App;

En este momento tenemos la aplicación donde nos muestra todos los usuario que disponemos en la variable.

Ahora queremos que los usuarios se vayan quitando según las letras que vayamos insertando en el input ya que estamos haciendo una búsqueda por nombre para encontrar a la persona que queremos.

Para esto necesitamos tres cosas:

  • Crear un método onChange en el Input
  • Crear un estado que por defecto será un texto vacío e irá cambiando según el valor del Input
  • Crear un filtro en la variable de users antes de hacer el map

El funcionamiento seria: cuando yo escribo en el Input, se ejecutará, por cada pulsación del teclado, el método onChange.

Esté método hará que el estado de la aplicación se modifique en tiempo real.


   const [search, setSearch] = useState("");

  
 <input className="form-control" type="text" onChange={e => { setSearch(e.target.value) }} placeholder="Search" />

Cuando usemos el estado en el filtro nos dejará solo los usuarios que dispongan de esas letras que hemos insertado en el Input, por lo que cuando realicemos el método «map» solo se visualizaran en la página o DOM los usuarios que han pasado el filtro.

   {
     allusers.filter(user => {
       if (search === "") return user;
       else if 
          (user.name.toLowerCase().includes(search.toLowerCase()))
              return user
     }).map(user => {
          return (
            <tr>
               <td>{user.id}</td>
               <td>{user.name}</td>
               <td>{user.dept}</td>
               <td>{user.phone}</td>
            </tr>
         )
    })
  }

Como podeis ver en el filtro por cada usuario se verifica si el estado está vacío para mostrar todos o si el nombre del usuario convertido todo en minúsculas (método «toLowerCase()») incluye (método «includes()») el valor del estado «search» también convertido en minúsculas (método «toLowerCase()»).

Si lo incluye, se devuelve el usuario pero si no lo incluye lo elimina. Por lo que cuando se hace el método «map» solo mostrará los usuarios que han pasado el filtro.

NOTA: si quieres que además del nombre también busque en otros campos solo tienes que crear tantas verificaciones como campos quieras que se busquen.

Por lo que el código quedaria de la siguiente forma:

import './App.css';
import users from './users';
import { useState } from "react"
import "../node_modules/bootstrap/dist/css/bootstrap.min.css"

function App() {

  const [search, setSearch] = useState("");
  const allusers = users;

  return (
    <>
      <div className='container'>
        <h1>Usuarios</h1>
        <input className="form-control" type="text" onChange={e => { setSearch(e.target.value) }} placeholder="Search" />
        <table className="table table-striped">
          <thead>
            <tr>
              <td>ID</td>
              <td>Name</td>
              <td>Departmet</td>
              <td>Phone</td>
            </tr>
          </thead>
          <tbody>
            {
              allusers.filter(user => {
                if (search === "") return user;
                else if (user.name.toLowerCase().includes(search.toLowerCase()))
                  return user
              }).map(user => {
                return (
                  <tr>
                    <td>{user.id}</td>
                    <td>{user.name}</td>
                    <td>{user.dept}</td>
                    <td>{user.phone}</td>
                  </tr>
                )
              })
            }
          </tbody>
        </table>
      </div>
    </>
  );
}

export default App;

Si quieres todo el proyecto, lo puedes bajar desde mi github en este enlace:

https://github.com/JangelMartinez/search

Si necesitas alguna aclaración, puedes dejarme un comentario o ir a la opción de contactar y enviarme un mensaje.

Hasta el próximo post :).

Deja un comentario