25. Un dato es del tipo que es, también en JavaScript

28/04/20191 Min lectura — En React, Client, JavaScript, 😞

Aparece un error, una y otra vez. De esos genéricos a la par que particulares, porque no hay forma de poder encontrar ayuda.

Al renderizar la página del listado de Quotes el resultado siempre es el mismo:

TypeError: this.props.quotes.map is not a function

Ensalada de console.log al canto, también de hacer debug como hay que hacerlo, a través de la consola y herramientas de desarrollador de Google Chrome.

NADA.

No hay ningún camino que te libre del error salvo que dejes de "pintar" el listado. Menudo remedio...

Pasan algunos días, lees, miras, pruebas.

TODO SIGUE IGUAL.

En el colmo de la desesperación te has llevado el código a otra parte para aislar el problema. Allí funciona todo.

Y de repente, después de un desayuno con tostada con un buen aceite de oliva descubres que, aunque JavaScript no tiene tipado de datos, no es lo mismo Object que Array.

El problema estaba delante de mi, todo el rato.

En src/reducers/index.js tenemos esto:

const rootReducer = combineReducers({
quote: (state = {}, action) => action.payload || state
});

Mi API en /api/v1/quotes devuelve esto (solo el trozo de código inicial):

{
"data":
[ /* <--- Fíjate en este [ */
{
"type":"quote",
"id":"1",
"attributes":
{"id":1,
"author_id":"3089"
...

El action.payload es realmente la respuesta de la API desde el primer data que ves en el anterior fragmento de JSON.

Así es. En mi código digo que el state tiene que ser un Object con {} pero realmente estoy inyectando los datos de un Array con el JSON a través de ese [].

Finalmente lo que provoca el error es herencia, no solo de mi mala praxis, sino del comportamiento que redux introduce para facilitarnos la vida (en teoria).

El valor inicial del state en el reducer (el código de más arriba) es MUY importante. Porque de alguna forma estamos diciéndole a redux lo que tiene que esperar recibir cuando alteremos ese estado.

De esta manera si le cuento que está esperando un objeto y recibe un array, pues se lía y hace que esos datos luego no se carguen en el props. Y acabamos en el error que veíamos al principio del todo.

Menudo y terrible descubrimiento. ¡Mañana irá mejor!