简体   繁体   English

在 React Native 中连接 REST API

[英]Connecting REST API in React Native

I am trying to learn how to connect APIs in React Native.我正在尝试学习如何在 React Native 中连接 API。 I am using a sample API: https://reactnative.dev/movies.json我正在使用示例 API: https://reactnative.dev/movies.json

This is my code:这是我的代码:

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      dataSource: [],
    };
  }
  componentDidMount() {
    return fetch("https://reactnative.dev/movies.json")
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          loading: false,
          dataSource: responseJson.movies,
        });
      })
      .catch((error) => console.log(error)); //to catch the errors if any
  }
  render() {
    if (this.state.isLoading) {
      return (
        <View style={styles.container}>
          <ActivityIndicator size="large" color="#0c9" />
        </View>
      );
    } else {
      let products = this.state.dataSource.map((val, key) => {
        return (
          <View key={key} style={styles.item}>
            <Text>{val}</Text>
          </View>
        );
      });
      return (
        <View style={styles.container}>
          <Text>{products.title}</Text>
        </View>
      );
    }
  }
}

The problem occurs with my "products" variable.我的“产品”变量出现问题。 In debug mode, I was able to see the key and value pairs which were correct from the API.在调试模式下,我能够从 API 中看到正确的key value However, the products array is populated with objects rather than strings which are structured like this: Object {$$typeof: Symbol(react.element), type: "RCTView", key: "0", …}但是,products 数组填充的是对象而不是结构如下的字符串: Object {$$typeof: Symbol(react.element), type: "RCTView", key: "0", …}

My code returns the following error: this.state.dataSource.map is not a function我的代码返回以下错误: this.state.dataSource.map is not a function

EDIT: The answer below worked for the API I was using.编辑:下面的答案适用于我正在使用的 API。 Now I am trying a different API structured like this:现在我正在尝试一个不同的 API 结构如下:

{"prods":
    {
    "86400":{"slug":"86400","url":"/86400"},
    "23andme":{"slug":"23andme","url":"/23andme"}
}}

I am having trouble with the mapping again.我又遇到了映射问题。 This returns an error:这将返回一个错误:

return dataSource.map((val, key) => (
      <View key={key} style={styles.item}>
        <Text>{val.slug}</Text>
      </View>
    ));

First, there is a small typo in your example.首先,您的示例中有一个小错字。 In your component's constructor you specify a loading state variable, but in your render function you're using isLoading .在组件的构造函数中,您指定loading state 变量,但在您的render function 中,您使用的是isLoading Second, you're not mapping over your data correctly.其次,您没有正确映射数据。 It just looks like you need to specify what aspects of each movie you care about in your render function.看起来您需要在渲染 function 中指定您关心的每部电影的哪些方面。 JSX can't handle displaying a full javascript object which is what <Text>{val}</Text> ends up being in your code. JSX 无法处理显示完整的 javascript object 这就是<Text>{val}</Text>最终出现在您的代码中。 There are a few ways you can fix this.有几种方法可以解决此问题。 It's very common to just map over your results and display them directly.在您的结果上仅使用 map 并直接显示它们是很常见的。

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      dataSource: []
    };
  }
  
  componentDidMount() {
    return fetch("https://reactnative.dev/movies.json")
      .then(response => response.json())
      .then(responseJson => {
        this.setState({
          loading: false,
          dataSource: responseJson.movies
        });
      })
      .catch(error => console.log(error));
  }

  render() {
    const { loading, dataSource } = this.state;

    if (loading) {
      return (
        <View style={styles.container}>
          <ActivityIndicator size="large" color="#0c9" />
        </View>
      );
    }

    return dataSource.map((movie, index) => (
      <View key={movie.id} style={styles.item}>
        <Text>{movie.title}</Text>
      </View>
    ));
  }
}

You could also pull this out to a renderMovies method, which might help since you are trying to display these in a styled container.您也可以将其拉出到renderMovies方法,这可能会有所帮助,因为您试图在样式化的容器中显示它们。

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      dataSource: []
    };
  }
  
  componentDidMount() {
    return fetch("https://reactnative.dev/movies.json")
      .then(response => response.json())
      .then(responseJson => {
        this.setState({
          loading: false,
          dataSource: responseJson.movies
        });
      })
      .catch(error => console.log(error));
  }

  renderMovies() {
    const { dataSource } = this.state;

    return dataSource.map((movie, index) => (
      <View key={movie.id} style={styles.item}>
        <Text>{movie.title}</Text>
      </View>
    ));
  }

  render() {
    const { loading } = this.state;

    if (loading) {
      return (
        <View style={styles.container}>
          <ActivityIndicator size="large" color="#0c9" />
        </View>
      );
    }

    return (
      <View style={styles.container}>
        {this.renderMovies()}
      </View>
    );
  }
}

I have used Object.values() to restructure the object into an array我已经使用Object.values()将 object 重组为一个数组

  componentDidMount() {
    return fetch("https://reactnative.dev/movies.json")
      .then((response) => response.json())
      .then((responseJson) => {
        this.setState({
          loading: false,
          dataSource: Object.values(responseJson.movies),       //changed this
        });
      })
      .catch((error) => console.log(error));
  }

Try simple way.尝试简单的方法。 This code uses modern React practice and helps you to brush up your React skills in general.这段代码使用了现代的 React 实践,可以帮助你全面提升你的 React 技能。 Give a try.试一下。

import React, {useState, useEffect} from 'react';
import { Text, View, StyleSheet } from 'react-native';
import axios from 'axios'; //for fetching data 

export default function App() {
 //React Hook for state
const [ data, setData ] = useState ([]);

//React Hook Instead Of ComponentDidMount
useEffect(() => {
 const fetchData = async () => {
   const result = await axios(
     "https://reactnative.dev/movies.json",
   );

   setData(result.data.movies);
 };

 fetchData();
 }, []);

return (
 <View>
   <Text>{JSON.stringify(data)}</Text>
 </View>
);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM