Je me demande si React Native a un bogue qui doit être corrigé qui donne l'erreur suivante:
React Native: TypeError: undefined n'est pas un objet (évaluation '_this.props.data.map')
Je suis assez bon dans ce domaine et pourtant je n'arrive pas à comprendre pourquoi j'obtiens cette erreur lorsque j'assemble ce composant:
import { combineReducers } from "redux";
import auth from "./auth_reducer";
import jobs from "./jobs_reducer";
import likedJobs from "./likes_reducer";
export default combineReducers({
auth,
jobs,
likedJobs
});
J'ai vérifié et revérifié à travers diverses pratiques de débogage que le problème ne vient pas de mon créateur ou réducteur d'action et après divers refactors, j'ai fait fonctionner ceux-ci correctement.
J'ai décidé de faire le composant ci-dessus à partir de zéro alors qu'avant je réutilisais un autre composant et pourtant j'obtiens toujours l'erreur ci-dessus.
Je demande si c'est un bug avec RN parce que quelqu'un d'autre a publié un problème similaire mais ils n'ont pas obtenu la réponse dont ils avaient besoin.
Ce n'est pas un problème de portée avec ceci parce que si je le refactore comme ceci:
import { FETCH_JOBS } from "../actions/types";
const INITIAL_STATE = {
listing: []
};
export default function(state = INITIAL_STATE, action) {
switch (action.type) {
case FETCH_JOBS:
return action.payload;
default:
return state;
}
}
cela ne fait absolument rien pour moi, même message d'erreur. Le message disant que ce n'est pas un objet est également déroutant, c'est un tableau et map () ne peut parcourir que des tableaux, donc pas sûr de ce que ne pas être un objet a à voir avec lui.
Le composant ci-dessus est appelé dans cet écran:
import axios from "axios";
// import { Location } from "expo";
import qs from "qs";
import { FETCH_JOBS, LIKE_JOB } from "./types";
// import locationify from "../tools/locationify";
const JOB_ROOT_URL = "https://authenticjobs.com/api/?";
const JOB_QUERY_PARAMS = {
api_key: "5634cc46389d0d872723b8c46fba672c",
method: "aj.jobs.search",
perpage: "10",
format: "json"
};
const buildJobsUrl = () => {
const query = qs.stringify({ ...JOB_QUERY_PARAMS });
return `${JOB_ROOT_URL}${query}`;
};
export const fetchJobs = (region, callback) => async dispatch => {
try {
const url = buildJobsUrl();
let { data } = await axios.get(url);
dispatch({ type: FETCH_JOBS, payload: data });
callback();
} catch (e) {
console.log(e);
}
};
export const likeJob = job => {
return {
payload: job,
type: LIKE_JOB
};
};
Voici à quoi ressemble le créateur de l'action:
import React, { Component } from "react";
import { View, Text } from "react-native";
import { connect } from "react-redux";
import Swipe from "../components/Swipe";
class DeckScreen extends Component {
renderCard(job) {
return (
<Card title={job.title}>
<View style={styles.detailWrapper}>
<Text>{job.company}</Text>
<Text>{job.post_date}</Text>
</View>
<Text>
{job.description.replace(/<span>/g, "").replace(/<\/span>/g, "")}
</Text>
</Card>
);
}
render() {
return (
<View>
<Swipe data={this.props.jobs} renderCard={this.renderCard} />
</View>
);
}
}
const styles = {
detailWrapper: {
flexDirection: "row",
justifyContent: "space-around",
marginBottom: 10
}
};
function mapStateToProps({ jobs }) {
return { jobs: jobs.listing };
}
export default connect(mapStateToProps)(DeckScreen);
et réducteur:
renderCards = () => {
return this.props.data.map(item => {
return this.props.renderCard(item);
});
};
et le combineReducer est également configuré correctement:
import React, { Component } from "react";
import { View, Animated } from "react-native";
class Swipe extends Component {
renderCards() {
return this.props.data.map(item => {
return this.props.renderCard(item);
});
}
render() {
return <View>{this.renderCards()}</View>;
}
}
export default Swipe;
La liste : [] est basée sur la structure de la réponse que je reçois. Quand je console.log (data) ;, les données réelles qui m'intéressent sont à l'intérieur de la propriété listing . J'ai donc configuré INITIAL_STATE sur la liste par défaut pour être un tableau vide avec l'intention de m'assurer de pouvoir mapper sur le tableau et de ne pas m'inquiéter du cas où je n'ai pas encore récupéré la liste des travaux. Lorsque je vais directement au point de terminaison de l'API, vous pouvez le voir ci-dessous:
3 Réponses :
Je pense que le problème est simplement que this.props.jobs n'est pas défini. Votre état initial est défini comme {listing: []} , mais vous mapStateToProps exécutez {jobs: ...} .
Essayez de changer initialState en { jobs: []} , afin que cela fonctionne toujours sur votre premier rendu.
Je pense que votre mapStateToProps devrait être:
mapStateToProps = ({ jobs }) => {
return { jobs }
}
EDIT En fait, cela pourrait être encore mieux si vous 'nommez' correctement votre état dans votre réducteur, comme:
const INITIAL_STATE = { jobs: [] }
export default function(state = INITIAL_STATE, action) {
switch (action.type) {
case FETCH_JOBS:
const jobs = action.payload.listings.listing
return { ...state, jobs };
default:
return state;
}
}
Puis dans votre mapStateToProps:
mapStateToProps = (state) => {
return { jobs: listings.listing }
}
la liste : [] est basée sur la structure de la réponse que je reçois. Lorsque je console.log (data); , les données réelles qui me tiennent à cœur se trouvent à l'intérieur de la propriété listing . J'ai donc configuré le INITIAL_STATE sur la liste par défaut pour être un tableau vide avec l'intention de m'assurer de pouvoir mapper sur le tableau et de ne pas m'inquiéter du cas où je ne l'ai pas encore récupéré la liste des travaux.
Cependant, vous accédez à this.props.jobs lors de votre premier rendu. L'erreur se produit après ou avant la récupération des données? De plus, après avoir récupéré des données (dans votre créateur d'action), vous envoyez {listings: listing} comme charge utile mais votre mapToProps reçoit jobs.listing , est-ce que je me trompe?
export default combineReducers({
@Daniel essaie celui-ci :-)
et essayez d'utiliser le format ** ES6 **, il sera facile de comprendre les fonctions. const mapStateToProps = state => {return {miniStatement: state.miniStatement.miniStatement,}}
J'ai bien peur que ce soit faux: mapStateToProps a le paramètre state pas un objet le contenant, dans votre code, state ne serait pas défini. Veuillez également formater correctement vos réponses.
@josemigallas désolé de ne pas voir ces accolades Merci
Le problème est dans votre réducteur. Veuillez vous référer aux modifications ci-dessous:
import { FETCH_JOBS } from "../actions/types";
const INITIAL_STATE = {
listing: []
};
export default function(state = INITIAL_STATE, action) {
switch (action.type) {
case FETCH_JOBS:
const { listings } = action.payload
return {...state, listing: listings.listing}
default:
return state;
}
}
J'espère que cela vous aidera.
où est défini
props.data?Dans quel format les données recevez-vous du serveur?
@Codesingh,
format: 'json'.la clé de liste est-elle disponible dans la réponse?
@Codesingh, oui, je l'ai ajouté dans mon OP pour que vous puissiez le voir.