reactjs - FlashList usa un componente reutilizable mientras se desplaza
El estado isActive no se actualiza cuando se desplaza un poco hacia abajo. FlashList copia el componente anterior (no lo crea desde cero en cada desplazamiento). No quiero actualizar el estado isActive dentro de useEffect, porque causa problemas de rendimiento. Además, tengo que enviar y almacenar la propiedad isSelected de esa manera. ¿Cómo solucionar este problema? ¿Podrías sugerir una solución alternativa para eso?
Espero que si el valor de isSelected es verdadero, el color de fondo del contenedor sea rojo, de lo contrario gris.
Mis datos de prueba son algo así:
const data = new Array(50).fill(false);
data[1] = true;
Aquí está mi código de demostración:
import {StyleSheet, View} from 'react-native';
import React, {useState} from 'react';
import {FlashList} from '@shopify/flash-list';
interface CustomTestInterface {
isSelected: boolean;
}
const CustomTest = ({isSelected}: CustomTestInterface) => {
const [isActive, setIsActive] = useState<boolean>(isSelected);
return (
<View
style={{
height: 80,
width: '100%',
backgroundColor: isActive ? 'red' : 'gray',
marginTop: 10,
}}
/>
);
};
const Test = () => {
return (
<View style={{flex: 1, backgroundColor: 'green'}}>
<FlashList
data={data}
estimatedItemSize={80}
renderItem={({item}) => <CustomTest isSelected={item} />}
/>
</View>
);
};
export default Test;
const styles = StyleSheet.create({});
Respuesta #1
FlashList es rápido porque reutiliza componentes en lugar de destruirlos y crear nuevos. Debido a esto, mantiene el estado del componente anterior, por lo que tendrás que actualizar el estado cuando el componente sea reciclado:
import { StyleSheet, View, Text } from 'react-native';
import React, { useState, useRef } from 'react';
import { FlashList } from '@shopify/flash-list';
// add id to help keep track of component
const data = new Array(50).fill(null).map((_, i) => ({
id: i + 1,
isSelected: false,
}));
data[1].isSelected = true;
// made CustomTest props match flashlist's renderItem props
interface CustomTestInterface {
item: {
isSelected: boolean;
id: number;
};
index: number;
}
const CustomTest = (props: CustomTestInterface) => {
const { isSelected, id } = props.item;
const lastItemId = useRef(id);
const [isActive, setIsActive] = useState<boolean>(isSelected);
if (id !== lastItemId.current) {
console.log(`${lastItemId.current} has been recycled to ${id}`);
lastItemId.current = id;
setIsActive(isSelected);
}
return (
<View
style={{
height: 80,
width: '100%',
backgroundColor: isActive ? 'red' : 'gray',
marginTop: 10,
}}>
<Text>{id}</Text>
</View>
);
};
const Test = () => {
return (
<View style={{ flex: 1, backgroundColor: 'green' }}>
<FlashList
data={data}
estimatedItemSize={80}
renderItem={(props) => <CustomTest {...props} />}
/>
</View>
);
};
export default Test;
const styles = StyleSheet.create({});
Demostración
