Escenario
Estoy diseñando un formulario web en el que quiero mostrar un combo que se carga dinámicamente con una petición XHR.Problema
Los datos a cargar cuentan con miles de registros. Necesito un combo que se cargue de manera dinámica y disponga de un autocomplete para filtrar los resultos.Solución
React select es un módulo de React que he venido usando desde hace algún tiempo y siempre ha respondido a mis expectativas. Hasta ahora nunca lo había utilizado para cargar los datos de manera asíncrona. La diferencia es que, en vez de usar el componente por defecto, usamos react-select/async y la llamada loadOptions debe devolver un promise. Al final, he acabado descartando usar un react-select porque necesitaba cargar más de 7000 registros y por muy rápido y asíncrono que sea, la capacidad de reacción del combo disminuye considerablemente, afectando la experiencia de usuario. Aun así me he dicho que voy a dejar el código por aquí por si algún otro día me hace fata:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
import React from 'react'; let ReactDom = require('react-dom'); import AsyncSelect from 'react-select/async'; class OfficeSearch extends React.Component { constructor(props) { super(props); this.state = { selectedOffice: null, }; } getOfficesOptions = (inputValue) => { const url = '/api/office'; let request = new Request(url, { credentials: 'same-origin', headers: new Headers({ 'Content-Type': 'text/plain' }) }); return fetch(request, { method: 'get' }).then(response => response.json()); }; handleOfficeChange = selectedOffice => { this.setState( { selectedOffice }, () => console.log(`Option selected:`, this.state.selectedOffice) ); }; render() { const { selectedOffice } = this.state; return ( <AsyncSelect cacheOptions defaultOptions value={selectedOffice} getOptionLabel={o => o.code} getOptionValue={o => o.id} onChange={this.handleOfficeChange} loadOptions={this.getOfficesOptions} noOptionsMessage={() => 'No hay datos'} loadingMessage={() => 'Cargando…'} placeholder= 'Seleccionar…' /> ); } } let container = document.getElementById('office-search-container'); if (container !== null) { ReactDom.render(<OfficeSearch />, container); } |