Tengo una función que filtra los datos sobre los eventos de cambio. Funciona bien en lo que respecta a la filtración, pero el problema es con el evento onChange y setState
Estoy usando React Select para dar el valor onChange:
<Select id="status" isClearable={false} options={statusOptions} defaultValue={statusOptions[0]} onChange={(choice) => handleStatusFilter(choice.value)} />Aquí las opciones de estado son:
const statusOptions = [ { value: '', label: 'Clear' }, { value: 'draft', label: 'Draft' }, { value: 'ready', label: 'Ready' }, { value: 'expired', label: 'Expired' }, ] Ahora el evento onChange estoy llamando al handleStatusFilter :
// state const [status, setStatus] = useState('') // ** handleStatusFilter // ** Function to handle status filter const handleStatusFilter = (value) => { let updatedData = [] const dataToFilter = () => { if (title.length || type.length || createdAt.length || createdBy.length || status.length) { return filteredData } else { return results } } setStatus(value) if (value.length) { updatedData = dataToFilter().filter((item) => { const startsWith = item.status.toLowerCase().startsWith(value.toLowerCase()) const includes = item.status.toLowerCase().includes(value.toLowerCase()) if (startsWith) { return startsWith } else if (!startsWith && includes) { return includes } else return null }) setFilteredData([...updatedData]) setStatus(value) } } Por lo tanto, funciona la primera vez que el usuario selecciona cualquier opción, pero no al cambiar su selección después de eso. Por ejemplo; los datos se filtran cuando el usuario selecciona la opción draft . Pero cuando pasa directamente de draft a ready , no funciona, y si el usuario borra el estado presionando la opción Clear de statusOptions , y luego el usuario selecciona ready , entonces los datos se filtran con este valor correctamente.
Supongo que debería haber una forma de borrar el valor en Cambiar en lugar de Borrar manualmente seleccionando la cadena vacía. Entonces, cómo contrarrestar este problema, ¿hay algún mejor enfoque a seguir, en lugar del método setState?
El problema es más o menos con esta condición aquí:
const dataToFilter = () => { if (title.length || type.length || createdAt.length || createdBy.length || status.length) { return filteredData } else { return results } } Probablemente devuelve results en la primera selección porque todos los valores en la condición son falsos. Seguro que status.length es 0 y, por lo tanto, es falsy . A partir de ese momento, siempre devuelve filteredData , ya que status.length es veraz. Obviamente, los valores filtrados ya no incluyen los otros valores. Entonces, independientemente de lo que seleccione, siempre volverá a filtrar los datos filtrados.
En su lugar, debe filtrar los results del valor original en cada selección.
updatedData = results.filter( // here use results instead of filtered values. (item) => { const startsWith = item.status.toLowerCase().startsWith(value.toLowerCase()) const includes = item.status.toLowerCase().includes(value.toLowerCase()) /** besides that, this can be simplified if (startsWith) { return startsWith } else if (!startsWith && includes) { return includes } else return null })**/ return startsWith || includesEdit1: Lo que dije anteriormente no está mal, pero no considera los otros filtros. Entonces, en general, está restringiendo sus resultados para que no puedan filtrarse más. En su lugar, debe aplicar todos los filtros en la misma función de filtro para filtrar los valores. Aquí hay un codesandbox con un ejemplo completo.
Usé un useEffect para eso y una simple selección de html para la demostración. Pero puede aplicar eso fácilmente a su código.