Cuando abro la aplicación por primera vez, obtiene los datos de la API, pero cuando actualizo la página dice No se pueden leer las propiedades de undefined (leyendo 'memes') . Cuando hago console.log el elemento de la tienda, muestra un objeto vacío, pero puedo ver la API con la extensión Redux Devtools. Me quedé atascado con este problema y no puedo resolverlo durante dos días.
rebanada.js
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; export const fetchJson = createAsyncThunk( "json/fetchJson", async () => { const data = await fetch("https://api.imgflip.com/get_memes"); const json = await data.json(); return json; } ); export const loadJsonSlice = createSlice({ name: "loadJson", initialState: { isLoading: false, hasError: false, memes:{} }, extraReducers: (builder) => { builder .addCase(fetchJson.pending, (state) => { state.isLoading = true; state.hasError = false; }) .addCase(fetchJson.fulfilled, (state, action) => { state.isLoading = false; state.memes = action.payload; }) .addCase(fetchJson.rejected, (state, action) => { state.isLoading = false; state.hasError = true; state.memes = {}; }); } }); export default loadJsonSlice.reducer; export const selectAllJson = (state) => state.loadJsonReducer.memes; export const isLoading = (state) => state.loadJsonReducer.isLoading;pantalla.js
import { useEffect, useState } from "react"; import { useSelector, useDispatch } from "react-redux"; import { selectAllJson, isLoading, fetchJson } from "./jsonSlice"; const DisplayJson = () => { const allMemes = useSelector(selectAllJson); const dispatch = useDispatch(); useEffect(() => { dispatch(fetchJson()); console.log(allMemes.data.memes[0].id); //Here is where the code gives error. }, [dispatch]); if (useSelector(isLoading)) { return <h1 style={{ fontSize: "48px" }}>WAIT PUST</h1>; } return <div>{allMemes.data.memes[0].id}</div>; //Here is where the code gives error. }; export default DisplayJson;tienda.js
import { configureStore } from "@reduxjs/toolkit"; import loadJsonSlice from "./jsonSlice"; const store = configureStore({ reducer: { loadJsonReducer: loadJsonSlice } }); export default store;Creo que tiene una pequeña falta de comprensión de cómo funciona la asincronía en JavaScript.
Su código en slide.js es correcto y funcionará.
Sin embargo, su display.js tiene que esperar a que se complete la acción asincrónica antes de poder acceder al estado.
useEffect(() => { // This dispatch will return a Promise, only after the promise resolves you can access the data dispatch(fetchJson()); console.log(allMemes.data.memes[0].id); //Here is where the code gives error. }, [dispatch]); Asegúrate de verificar si allMemes ya está completo cuando accedes a él:
const allMemes = useSelector(selectAllJson); console.log('memes: ', allMemes); // initially 'undefined' but eventually populated via your thunk // When using memes, make sure it is populated return allMemes ? allMemes.data.memes[0].id : 'Loading...';Creo que esta solución funciona, pero el motivo del error no es el tipo asíncrono de su solicitud de recuperación. El motivo de este error es el cierre actual de su función de efecto. Citado por Eric Elliott:
"Un cierre es la combinación de una función agrupada (encerrada) con referencias a su estado circundante (el entorno léxico). En otras palabras, un cierre le da acceso al alcance de una función externa desde una función interna. En JavaScript, los cierres son creado cada vez que se crea una función, en el momento de la creación de la función".
Consulte también este enlace: https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36
Dependiendo de esto, todos los Memes en la función de efecto serán un objeto vacío (como su inicialización) también al enviar un objeto de acción y no un procesador.