Estoy tratando de incluir un mecanismo de favoritos en mis códigos nativos de reacción, pero tengo un problema:
Cuando la página se muestra primero, la función favs.includes funciona como se esperaba. Pero cuando hice clic en el botón de favoritos, aparece un error
TypeError: favs.includes is not a function. (In 'favs.includes(id)', 'favs.includes' is undefined)
const getFavs = async () => { await AsyncStorage.getItem("favs").then((res) => { if (res !== [] && res !== null && res !== "") { return setFavs(JSON.parse(res)); } else { return setFavs([]); } }); }; useEffect(() => { getFavs(); console.log(favs.includes(id)); return console.log(typeof favs); }, []); return ( <View style={{ alignItems: "center", justifyContent: "center" }}> {favs.includes(id) ? ( <TouchableOpacity onPress={() => { AsyncStorage.removeItem("favs", id); }} > <Icon name="star" size={25} color="orange" solid /> </TouchableOpacity> ) : ( <TouchableOpacity style={{ height: 100, width: 100, backgroundColor: "red" }} onPress={() => { console.log(typeof favs); setFavs(favs.push(id)); console.log(typeof favs); AsyncStorage.setItem("favs", JSON.stringify(favs)); setFav(true); }} > <Icon name="star" size={25} color="orange" /> </TouchableOpacity> )} </View> );El problema radica en esta línea en su controlador de clics
setFavs(favs.push(id)) que establece favs en un número, no en una matriz. Array#push() devuelve la nueva longitud de la matriz después de la inserción, no la matriz en sí. consulte ¿Por qué Array.prototype.push devuelve la nueva longitud en lugar de algo más útil? .
Además, usar push() en una matriz de estado muta la matriz, en su lugar debería
setFavs(prevFavs => [...prevFavs, id]) // or setFavs(prevFavs => prevFavs.concat(id)) Su último error supone que llamar a console.log después de su llamada setState reflejará el cambio de estado cuando, de hecho, registrará el valor de estado anterior (actual). El valor de estado actualizado no estará disponible hasta el siguiente ciclo de renderizado. ver ¿Por qué llamar al método setState de reacción no muta el estado inmediatamente?
Creo que generalmente se debe a que el componente se representó al principio, el estado de favs aún está vacío o la función asíncrona getFavs no se completó.
Tal vez pueda intentar dar una condición a donde favs.includes invocado como:
{favs && favs.includes && favs.includes(id)? // make sure favs is truthy and favs.includes property existed <TouchableOpacity onPress={()=>{ AsyncStorage.removeItem('favs',id); }}> <Icon name = "star" size={25} color="orange" solid /> </TouchableOpacity > : <TouchableOpacity style={{height:100,width:100,backgroundColor:'red'}} onPress={()=>{ console.log(typeof(favs)) setFavs(favs.push(id)) console.log(typeof(favs)) AsyncStorage.setItem('favs',JSON.stringify(favs)) setFav(true) }}> <Icon name = "star" size={25} color="orange" /> </TouchableOpacity > }Por favor, hágamelo saber si esto resuelve su problema o no, gracias
Veo dos problemas con tu código.
En primer lugar, no veo su uso useState . Debería ser
const [favs, setFavs] = useState([]); En segundo lugar, está mezclando código asincrónico y sincrónico. Está llamando a getFavs , que contiene una llamada al almacenamiento asíncrono que se ejecuta "fuera" del hilo del programa principal. E inmediatamente después de eso, está llamando a favs.includes() , que por supuesto no funcionará, porque la llamada asíncrona aún no se realizó.