2017-09-02 1 views
0

D'abord, je veux commencer par dire que je suis un total noob à React Native et Shoutem. Je ne suis pas sûr si je devrais écrire Shoutem ou Réagir Native dans le sujet de mes questions, mais voici mon problème.Shoutem récupérer les données n'affiche pas

J'ai deux écrans:

  1. Screen1.js
  2. Screen2.js

Screen1 affiche une liste des articles retournés d'une extraction. Une fois que je clique sur l'élément, il va ouvrir le deuxième écran qui est l'écran de détails.

Je passe des données de screen1 à screen2. En screen2 j'ai besoin de faire un autre appel de récupération pour différentes données, mais cela ne fonctionne pas. Je fais exactement la même chose sur les deux écrans.

Voici mon code pour Screen1:

import React, { 
    Component 
} from 'react'; 

import { 
    ActivityIndicator, 
    TouchableOpacity 
} from 'react-native'; 

import { 
    View, 
    ListView, 
    Text, 
    Image, 
    Tile, 
    Title, 
    Subtitle, 
    Overlay, 
    Screen 
} from '@shoutem/ui'; 

import { 
    NavigationBar 
} from '@shoutem/ui/navigation'; 

import { 
    navigateTo 
} from '@shoutem/core/navigation'; 

import { 
    ext 
} from '../extension'; 

import { 
    connect 
} from 'react-redux'; 

export class List extends Component { 
    constructor(props) { 
    super(props); 
    this.renderRow = this.renderRow.bind(this); 
    this.state = { 
     isLoading: true, 
     content: null, 
    } 

    } 

    componentDidMount() { 
    return fetch('https://www.cannabisreports.com/api/v1.0/strains').then((response) => response.json()).then((responseData) => { 
     this.setState({ 
     isLoading: false, 
     content: responseData 
     }); 
    }).done(); 
    } 

    renderRow(rowData) { 
    const { navigateTo } = this.props; 

    return (
     //<Text>{rowData.name}, {rowData.createdAt.datetime}</Text> 
     <TouchableOpacity onPress={() => navigateTo({ 
      screen: ext('Strain'), 
      props: { rowData } 
     })}> 
      <Image styleName="large-banner" source={{ uri: rowData.image && 
      rowData.image ? rowData.image : undefined }}> 
      <Tile> 
       <Title>{rowData.name}</Title> 
       <Subtitle>none</Subtitle> 
      </Tile> 
      </Image> 
     </TouchableOpacity> 
    ); 
    } 

    render() { 
    if (this.state.isLoading) { 
     return (
     <View style={{flex: 1, paddingTop: 20}}> 
      <ActivityIndicator /> 
     </View> 
    ); 
    } 

    return (
     <View style={{flex: 1, paddingTop: 20}}> 
     <ListView 
      data={this.state.content.data} 
      renderRow={rowData => this.renderRow(rowData)} 
     /> 
     </View> 
    ); 
    } 
} 

// connect screen to redux store 
export default connect(
    undefined, 
    { navigateTo } 
)(List); 

Je passe rowData à Screen2. J'ai ensuite besoin de faire un autre appel d'appel en utilisant les données de rowData car il s'agit d'un paramètre de chemin nécessaire pour l'appel de l'API dans Screen2.

Donc, fondamentalement, je dois faire FETCH appel à Screen2 comme ceci:

fetch('https://mywebsite.com/'+rowData.something+'/myotherdata') 
     .then((response) => response.json()) 
     .then((responseJson) => { 
     this.setState({ 
      content: responseJson.data 
     }) 
     }) 
     .catch((error) => { 
     console.error(error); 
     }); 

Voici mon code pour screen2:

export default class Strain extends Component { 

    constructor(props) { 
    super(props); 
    this.state = { 
     content: null, 
    } 
    } 

    componentDidMount() { 
    return fetch('https://mywebsite.com/'+rowData.something+'/myotherdata') 
     .then((response) => response.json()) 
     .then((responseJson) => { 
     this.setState({ 
      content: responseJson.data 
     }) 
     }) 
     .catch((error) => { 
     console.error(error); 
     }); 
    } 

    renderRow(dataContent) { 
    return (
     <Text>{dataContent.name}</Text> 
     // This does not work either -> <Text>{dataContent}</Text> 
    ); 
    } 

    render() { 
    const { rowData } = this.props; //This is coming from screen1.js 

    return (
     <ScrollView style = {{marginTop:-70}}> 
     <Image styleName="large-portrait" source={{ uri: rowData.image && 
     rowData.image ? rowData.image : undefined }}> 
      <Tile> 
      <Title>{rowData.name}</Title> 
      <Subtitle>{rowData.createdAt.datetime}</Subtitle> 
      </Tile> 
     </Image> 

     <Row> 
      <Text>Seed Company: {rowData.seedCompany.name}</Text> 
     </Row> 

     <Divider styleName="line" /> 

     <Row> 
      <Icon name="laptop" /> 
      <View styleName="vertical"> 
      <Subtitle>Visit webpage</Subtitle> 
      <Text>{rowData.url}</Text> 
      </View> 
      <Icon name="right-arrow" /> 
     </Row> 

     <Divider styleName="line" /> 

     <View style={{flex: 1, paddingTop: 20}}> 
      <ListView 
      data={content} 
      renderRow={dataContent => this.renderRow(dataContent)} 
      /> 
     </View> 

     <Divider styleName="line" /> 

     </ScrollView> 
    ); 
    } 
} 

Ma chercher renvoie URL données comme ceci:

{ 
    data: { 
    name: "7.5833", 
    another_name: "8.6000", 
    different_name: "5.7500", 
    } 
} 

Ceci renvoie uniquement un objet de données comme ce que vous voyez ci-dessus.

Quand je lance le code je reçois cette erreur: null is not an object (evaluating 'Object.keys(e[t])')

S'il vous plaît laissez-moi savoir si vous avez besoin de fournir plus d'informations.

J'ai essayé tellement de choses différentes et rien ne semble fonctionner alors j'ai besoin d'aide. Qu'est-ce que je fais mal?

+1

Savez-vous quel code appelle 'Object.keys (e [t])'? Si non, vous devez aller chercher dans votre navigateur devtools et comprendre cela. En outre, il n'est pas clair comment le code 'render()' de la question se rapporte à votre appel de récupération. Où est le code qui appelle réellement 'render()'? Dans 'this.setState ({ } contenu: responseJson.data }, function() { // faire quelque chose avec le nouvel état }); 'quel code est ce que la partie' // faire quelque chose avec un nouvel état 'appelle? Comment cela se rapporte-t-il au reste du code dans la question? – sideshowbarker

+0

@iamthestreets Où voyez-vous cette erreur? Cela ressemble à une erreur dans le code minifié, c'est donc difficile à dire, essayez d'exécuter une version de débogage pour obtenir des erreurs plus amicales. D'après ce que je peux dire, vous ne donnez pas à votre ListView le bon contenu. Soit 'this.state.content' ou faites' const {content} = this.state; 'en tant que première ligne de la fonction de rendu. C'est la meilleure pratique à déstructurer en premier (deuxième approche) et si le contenu n'est pas disponible rendre un espace réservé. – dodsky

+0

J'utilise Shoutem Builder pour exécuter l'application car c'est la seule façon pour moi d'obtenir des erreurs à afficher. @sideshowbarker J'ai enlevé 'function() {// fait quelque chose avec un nouvel état}' il n'est pas nécessaire. Je ne suis pas sûr de ce que vous voulez dire par quel code appelle 'render()'. lorsque l'écran se charge, il appelle 'render()'. – iamthestreets

Répondre

0

Je ne sais pas pourquoi cela fonctionne mais il le fait.

J'ai utilisé une fonction pour fetch mes données, puis appeler la fonction dans componentDidMount comme ceci:

getData() { 
    return fetch('https://mywebsite.com/myotherdata') 
     .then((response) => response.json()) 
     .then((responseJson) => { 
     this.setState({ 
      data: responseJson.data 
     }); 
     }) 
     .catch((error) => { 
     console.error(error); 
     }); 
    } 

    componentDidMount() { 
    this.getData(); 
    } 

ensuite pour obtenir les valeurs de la réponse JSON que je fais ceci: this.state.data.name

I J'ai un autre problème, mais je vais créer une autre question.