así que estoy tratando de implementar un cuadro de búsqueda con useState y useEffect. tenemos una matriz de objetos y queremos filtrarlos de acuerdo con nuestro término de búsqueda. aquí está mi implementación:
import React, {useEffect, useState} from "react"; const array = [ { key: '1', type: 'planet', value: 'Tatooine' }, { key: '2', type: 'planet', value: 'Alderaan' }, { key: '3', type: 'starship', value: 'Death Star' }, { key: '4', type: 'starship', value: 'CR90 corvette' }, { key: '5', type: 'starship', value: 'Star Destroyer' }, { key: '6', type: 'person', value: 'Luke Skywalker' }, { key: '7', type: 'person', value: 'Darth Vader' }, { key: '8', type: 'person', value: 'Leia Organa' }, ]; let available = [] const Setup = () => { const [state, setState] = useState(''); useEffect(() => { available = array.filter(a => a.value.startsWith(state)); },[state]) const show = state ? available : array; return <> <input value={state} onChange={e => setState(e.target.value)} type="text" className="form"/> {show.map(a => { return <Data id={a.key} key={parseInt(a.key)} value={a.value} type={a.type}/> })} </> } const Data = (props) => { return <> <div> <p>{props.value}</p> </div> </> } export default Setup;el problema comienza cuando le damos a nuestro cuadro de búsqueda un término de búsqueda válido (como 'T'). espero que cambie la salida en consecuencia (para mostrar solo 'Tatooine') pero la salida no cambia. mientras tanto, si agrega otro carácter al término de búsqueda (como 'a', que establecería nuestro término de búsqueda en 'Ta'), generará el resultado esperado. en otras palabras, el término de búsqueda no se aplica sincrónicamente. ¿Tienes alguna idea de por qué es eso?
El useEffect se activa cuando el componente se monta, se vuelve a renderizar o se desmonta. En su caso, el cambio del campo de búsqueda provoca un reprocesamiento debido al cambio de state . Esto da como resultado que useEffect se active después del cambio de estado y sea demasiado tarde para lo que necesita.
Si escribe "Ta" en su campo, verá que funciona, pero parece como si la búsqueda estuviera un paso atrás.
Simplemente puede eliminar el uso de useEffect y filtrar cuando renderiza. Esto significa que también puede eliminar toda la lógica en torno a las variables available y show :
const Setup = () => { const [state, setState] = useState(""); return ( <> <input value={state} onChange={(e) => setState(e.target.value)} type="text" className="form" /> {array .filter((a) => a.value.startsWith(state)) .map((a) => ( <Data id={a.key} key={parseInt(a.key, 10)} value={a.value} type={a.type} /> ))} </> ); };Hay buena información en los documentos Uso del gancho de efectos .
Simplemente agregue toLowerCase mehtod a su función de filtro. como esto:
import React, { useEffect, useState } from "react"; const array = [ { key: "1", type: "planet", value: "Tatooine" }, { key: "2", type: "planet", value: "Alderaan" }, { key: "3", type: "starship", value: "Death Star" }, { key: "4", type: "starship", value: "CR90 corvette" }, { key: "5", type: "starship", value: "Star Destroyer" }, { key: "6", type: "person", value: "Luke Skywalker" }, { key: "7", type: "person", value: "Darth Vader" }, { key: "8", type: "person", value: "Leia Organa" } ]; let available = []; const Setup = () => { const [state, setState] = useState(""); useEffect(() => { available = array.filter((a) => a.value.toLowerCase().startsWith(state)); }, [state]); const show = state ? available : array; return ( <> <input value={state} onChange={(e) => setState(e.target.value)} type="text" className="form" /> {show.map((a) => { return ( <Data id={a.key} key={parseInt(a.key)} value={a.value} type={a.type} /> ); })} </> ); }; const Data = (props) => { return ( <> <div> <p>{props.value}</p> </div> </> ); }; export default Setup;y aquí está el ejemplo de trabajo: here
Simplemente puede sacar useEffect.
import React, { useState } from 'react'; const array = [ { key: '1', type: 'planet', value: 'Tatooine' }, { key: '2', type: 'planet', value: 'Alderaan' }, { key: '3', type: 'starship', value: 'Death Star' }, { key: '4', type: 'starship', value: 'CR90 corvette' }, { key: '5', type: 'starship', value: 'Star Destroyer' }, { key: '6', type: 'person', value: 'Luke Skywalker' }, { key: '7', type: 'person', value: 'Darth Vader' }, { key: '8', type: 'person', value: 'Leia Organa' }, ]; let available = []; const Setup = () => { const [state, setState] = useState(''); available = array.filter(a => a.value.startsWith(state)); const show = state ? available : array; return ( <> <input value={state} onChange={e => setState(e.target.value)} type='text' className='form' /> {show.map(a => { return ( <Data id={a.key} key={parseInt(a.key)} value={a.value} type={a.type} /> ); })} </> ); }; const Data = props => { return ( <> <div> <p>{props.value}</p> </div> </> ); }; export default Setup;