Específicamente con Material UI, estoy tratando de generar una gran cantidad de entradas (> 100) y administrar un estado global de manera efectiva. Me encuentro con serios problemas de rendimiento, como un retraso de entrada de alrededor de 50 entradas, pero el retraso sigue siendo notable en alrededor de 10 entradas. Lo reduje al componente Material UI <TextField /> porque si lo cambio a un elemento de input normal, prácticamente no hay retraso, lo que es de esperar, ya que suceden muchas más cosas en un componente MUI.
Sin embargo, lo que no sé es si cambiar la forma en que administro el estado podría ayudar al rendimiento. Probé 2 enfoques de administración de estado: reacción tradicional con useState hook y Recoil.
Además de los 2 enfoques anteriores, también probé una combinación de retroceso y reacción tradicional usando useState y useSetRecoilState en los componentes del filtro para que todos los filtros no se volvieran a procesar al cambiar al estado de retroceso, ya que solo escriben, no leen, pero aún así sin suerte.
EDITAR
Resulta que olvidé probar poner valores en más de 1 entrada... Cuando ingresas un valor en otra entrada, la entrada ingresada anteriormente se borrará. Estoy pensando que es porque en mi función handleChange , reemplazo un elemento en filterList pero filterList ahora es una referencia obsoleta, por lo que no tiene el valor establecido anteriormente. Volvamos al punto de partida ahora, porque si leo el estado en el componente de filtro, entonces el componente se volverá a procesar, lo que elimina el aumento de rendimiento de la nota.
EDITAR 2
Solución publicada a continuación
Parece que estaba tratando de usar el retroceso cuando realmente no lo necesitaba. Usar React.memo junto con React.useState y mover la edición de estado global al padre terminó siendo todo lo que necesitaba.
Filtros.js
const filterMaker = (length) => { let filters = []; for (let i = 0; i < length; i++) { if (i % 2 === 0) { filters.push({ name: `filter-${i}`, type: 'a', active: { value1: '' } }); } else { filters.push({ name: `filter-${i}`, type: 'b', active: { value1: '', value2: '' }, }); } } return filters; }; function replaceItemAtIndex(arr, index, newValue) { return [...arr.slice(0, index), newValue, ...arr.slice(index + 1)]; } export default function Filters() { const [filterList, setFilterList] = useRecoilState(filterListState); useEffect(() => { setFilterList(filterMaker(200)); }, []); const handleChange = (filter, name, value, index) => { setFilterList((prevState) => { return replaceItemAtIndex(prevState, index, { ...filter, active: { ...filter.active, [name]: value, }, }); }); }; return ( <div> {filterList.map((filter) => filter.type === 'a' ? ( <FilterA key={filter.name} filter={filter} filterList={filterList} handleChange={handleChange} /> ) : ( <FilterB key={filter.name} filter={filter} filterList={filterList} handleChange={handleChange} /> ) )} </div> ); }FiltroA.js
export const FilterA = memo( ({ filter, filterList, handleChange }) => { const [values, setValues] = useState(filter.active || {}); const index = filterList.findIndex((item) => item.name === filter.name); const handleLocalChange = ({ target: { name, value } }) => { setValues((prevState) => { return { ...prevState, [name]: value }; }); handleChange(filter, name, value, index); }; return ( <Box mb={1}> <Typography>{filter.name}</Typography> <TextField variant="standard" name="value1" label="value1" value={values.value1 || ''} onChange={handleLocalChange} /> </Box> ); }, (prevProps, nextProps) => { if (prevProps.filter.active.value1 === nextProps.filter.active.value1) { return true; } return false; } );