web-dev-qa-db-fra.com

Récupération de JSON et itération à travers les valeurs de react-native

Je suis nouveau pour réagir en natif, et j'essaye simplement de parcourir un exemple de fichier json mais je reçois l'erreur undefined n'est pas une fonction (évaluer 'this.state.results.map')

J'ai initialement défini l'état sur un objet, donc je ne sais pas pourquoi je reçois cette erreur.

Voici le JS :

import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View, StyleSheet, TouchableHighlight } from 'react-native';

var REQUEST_URL = 'https://facebook.github.io/react-native/movies.json';

class WPReact extends Component {
  constructor(props) {
    super(props);
    this.state = {results: []};
  }
  componentDidMount() {
    this.fetchData();
  }
  fetchData() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          results : { responseData }
        });
      })
      .done();
  }
  render() {
    return this.renderJSON();
  }
  renderJSON() {
    contents = this.state.results.map((item) => {
      <View key={item.movies.title} style={ styles.container }>
        <Text style={styles.title}>
          {item.movies.title}
        </Text>
      </View>
     });
    return (
      <View style={styles.container}>
        {contents}
      </View>
    );
  }
}

var Dimensions = require('Dimensions');

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#FFFFFF',
  },
  textContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 30,
    textAlign: 'center',
    margin: 10,
  },
  text: {
    fontSize: 18,
    paddingLeft: 20,
    paddingRight: 20,
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

// App registration and rendering
AppRegistry.registerComponent('AwesomeProject', () => WPReact);

MODIFIER

J'ai donc modifié la renderJSON () et supprimé les accolades de responseData comme vous l'avez dit, car il s'agissait déjà d'un objet:

renderJSON() {

    console.log(this.state.results.description);
    contents = this.state.results.movies.map((item) => {
      <View key={item.title} style={ styles.container }>
        <Text style={styles.title}>
          {item.title}
        </Text>
      </View>
     });
    return (
      <View style={styles.container}>
        {contents}
      </View>
    );
  }

J'ai ajouté un journal de la console pour voir si je pouvais sortir une partie des données, et je peux voir la description. L’échantillon JSON que j’utilise est (démo de react):

{
  "title": "The Basics - Networking",
  "description": "Your app fetched this from a remote endpoint!",
  "movies": [
    { "title": "Star Wars", "releaseYear": "1977"},
    { "title": "Back to the Future", "releaseYear": "1985"},
    { "title": "The Matrix", "releaseYear": "1999"},
    { "title": "Inception", "releaseYear": "2010"},
    { "title": "Interstellar", "releaseYear": "2014"}
  ]
}

Je peux enregistrer la description et le titre. Mais je reçois toujours: ReactNativeJS: undefined is not an object (evaluating 'this.state.results.movies.map')

Et si j'essaie d'enregistrer console.log(this.state.results.movies[0].title) je reçois undefined is not an object (evaluating 'this.state.results.movies[0]') 

fetchData() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        console.log(responseData);
        this.setState({
          results : responseData
        });
      })
      .done();
  }

console.log (responseData) indique:

03-29 13:49:53.028  3062  4143 I ReactNativeJS: { title: 'The Basics - Networking',
03-29 13:49:53.028  3062  4143 I ReactNativeJS:   description: 'Your app fetched this from a remote endpoint!',
03-29 13:49:53.028  3062  4143 I ReactNativeJS:   movies: 
03-29 13:49:53.028  3062  4143 I ReactNativeJS:    [ { title: 'Star Wars', releaseYear: '1977' },
03-29 13:49:53.028  3062  4143 I ReactNativeJS:      { title: 'Back to the Future', releaseYear: '1985' },
03-29 13:49:53.028  3062  4143 I ReactNativeJS:      { title: 'The Matrix', releaseYear: '1999' },
03-29 13:49:53.028  3062  4143 I ReactNativeJS:      { title: 'Inception', releaseYear: '2010' },
03-29 13:49:53.028  3062  4143 I ReactNativeJS:      { title: 'Interstellar', releaseYear: '2014' } ] }

console.log (this.state.results.movies);

03-29 14:18:05.483  3062  4726 I ReactNativeJS: undefined
03-29 14:18:05.510  3062  4726 I ReactNativeJS: [ { title: 'Star Wars', releaseYear: '1977' },
03-29 14:18:05.510  3062  4726 I ReactNativeJS:   { title: 'Back to the Future', releaseYear: '1985' },
03-29 14:18:05.510  3062  4726 I ReactNativeJS:   { title: 'The Matrix', releaseYear: '1999' },
03-29 14:18:05.510  3062  4726 I ReactNativeJS:   { title: 'Inception', releaseYear: '2010' },
03-29 14:18:05.510  3062  4726 I ReactNativeJS:   { title: 'Interstellar', releaseYear: '2014' } ]
5
narutoramen

Je vois quelques choses que vous devez changer.

Tout d'abord, vous devez lier la méthode fetchData lorsque vous utilisez ES6 en faisant ceci this.fetchData = this.fetchData.bind(this); dans le constructeur (recherchez d'autres moyens de le faire).

Deuxièmement, map devrait être appliqué à this.state.results.movies car il s’agit du tableau (suivant votre message). this.state.results n'est pas un tableau, c'est un objet contenant un tableau.

import React, { Component } from 'react';
import { AppRegistry, ListView, Text, View, StyleSheet, TouchableHighlight } from 'react-native';

var REQUEST_URL = 'https://facebook.github.io/react-native/movies.json';

class WPReact extends Component {
  constructor(props) {
    super(props);

    this.state = {
      //Lets initialize results with the same struct we expect to receive from the api
      results: {
        title: '',
        description: '',
        movies: []
      }
    };
    //Using ES6 we need to bind methods to access 'this'
    this.fetchData = this.fetchData.bind(this);
  }

  componentDidMount() {
    this.fetchData();
  }

  fetchData() {
    fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        this.setState({
          results: responseData
        });
      })
      .done();
  }

  render() {
    //this.state.results.movies is the array you have to iterate
    contents = this.state.results.movies.map((item) => {
      //We need to return the corresponding mapping for each item too.
      return (
          <View key={item.title} style={ styles.container }>
            <Text style={styles.title}>
              {item.title}
            </Text>
          </View>
        );
     });
    return (
      <View style={styles.container}>
        {contents}
      </View>
    );
  }
}

var Dimensions = require('Dimensions');

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#FFFFFF',
  },
  textContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 30,
    textAlign: 'center',
    margin: 10,
  },
  text: {
    fontSize: 18,
    paddingLeft: 20,
    paddingRight: 20,
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

// App registration and rendering
AppRegistry.registerComponent('AwesomeProject', () => WPReact);

Faites-moi savoir si cela fonctionne, je n'ai pas encore testé, mais je vais bientôt.

4
Facundo La Rocca

Les composants React utilisant des classes ES6 ne permettent pas à __autorienter this de ne pas utiliser les méthodes React. Dans votre constructeur, ajoutez:

this.renderJSON = this.renderJSON.bind(this)

0
Jérôme

responseData doit être un tableau pour que la méthode Array#map() soit disponible en tant que méthode sur celle-ci.

Vous définissez results sur un objet contenant la valeur de votre responseData:

this.setState({ 
  results : { responseData } // Object literal notation albeit possibly incorrect depending on the value of responseData
});

Supprimez les accolades si vous êtes sûr que responseData est un tableau:

this.setState({ 
  results :  JSON.parse(responseData);
  // You'll want to parse your JSON data here too :)
  // If responseData is an array, you'll be able to call .map on it
});

// this.state.results.movies.map should now work
// (given the structure of the expected JSON)
0
Pineda