查询 api 时出错:这适用于网络浏览器,但不适用于移动设备。 (世博会)

Error querying the api: This works in the web browser but not on mobile. (expo)

我是 React Native 的新手,我无法使用这个 api,当我在浏览器中启动这个应用程序时,它工作正常,但是当我进入 expo 应用程序时它没有'显示宠物小精灵图像,有人可以帮助我吗?

import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button, Alert, TextInput, Image } from 'react-native';

interface PokeInterface {
  sprites : {
    back_default : string;
  }
}
export default function App() {
  const [text, setText] = useState<string>("")
  const [response, setResponse] = useState<PokeInterface | any>()
  const [image, setImage] = useState<string>()
  const handleText = (text : string) => {
    setText(text)
  }

  const searchApi = (pokemonName : string) => {
    fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}/`, { method: 'GET'})
      .then((response) => response.json())
        .then((response) => setResponse(response))

        
  }
  useEffect(() => {
    if(text){
      searchApi(text)
    }
    if(response){
      const {sprites} = response
      setImage(sprites.front_default)
    }

    return () => {
      if(image){
        setImage("")
      }
    }
  },[text, response])

  return (
    <View style={styles.container}>
      <View style={styles.topbar}>
        <Text style={styles.title}>Pokedex Mobile</Text>
        <TextInput
          style={styles.input}
          onChangeText={(value: any) => handleText(value)}
          value={text}
          placeholder="Search Pokemon"
          keyboardType="default"
        />
        <Text style={styles.text}>{text}</Text>
      </View>
      {image && (
        <Image 
          style={styles.logo} 
          source={{uri : `${image}`}}
          />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  text : {
    fontSize: 30,
    color : "red"
  },
  input: {
    height: 40,
    margin: 12,
    borderWidth: 1,
    padding: 10,
  },
  container : {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center'
  },
  title: {
    fontSize: 30,
    color: '#000'
  },
  topbar: {
  },
  logo : {
    width: 200,
    height: 200
  }
});
import React, {useEffect, useState} from 'react';
import {StyleSheet, Text, View, TextInput, Image, Button} from 'react-native';

// Sorry for removing the types i was using JS
// This code works test it for yourself
export default function App() {
  const [text, setText] = useState('');
  const [response, setResponse] = useState(); // Here use PokeInterface || any as you are doing conditional checking
  const [image, setImage] = useState();
  const handleText = e => {
    setText(e);
  };

  const searchApi = pokemonName => {
    fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}/`, {method: 'GET'})
      .then(response => response.json())
      .then(response => setResponse(response));
  };
  useEffect(() => {
    if (response) {
      const {sprites} = response;
      console.log(response);
      setImage(sprites.front_default);
    }
    return () => {
      if (image) {
        setImage('');
      }
    };
  }, [image, text, response]); // you have to pass all the dependencies so useEffect will be invoked as you didnt pass image dep the useeffct was not invoking

  return (
    <View style={styles.container}>
      <View style={styles.topbar}>
        <Text style={styles.title}>Pokedex Mobile</Text>
        <TextInput
          style={styles.input}
          onChangeText={(value: any) => handleText(value)}
          value={text}
          placeholder="Search Pokemon"
          keyboardType="default"
        />
        <Text style={styles.text}>{text}</Text>
      </View>
      {image && <Image style={styles.logo} source={{uri: `${image}`}} />}
      <Button
        title={'Submit'}
        onPress={() => searchApi(text)}
        disabled={!text}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  text: {
    fontSize: 30,
    color: 'red',
  },
  input: {
    height: 40,
    margin: 12,
    borderWidth: 1,
    padding: 10,
  },
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  title: {
    fontSize: 30,
    color: '#000',
  },
  topbar: {},
  logo: {
    width: 200,
    height: 200,
  },
});

您当前的代码导致无限循环...

  1. 您输入了一些触发 searchApi(text)
  2. 的文本
  3. 写入 response 触发你的效果挂钩
  4. 因为text仍然真实,它再次触发searchApi(text)
  5. 转到#2

据我所知,您可以简单地丢弃大部分 response 并在文本更改时只检索图像。

// this doesn't need to be defined in your component
const getPokemonImage = async (name: string) => {
  const res = await fetch(
    `https://pokeapi.co/api/v2/pokemon/${encodeURIComponent(pokemonName)}/`
  );

  if (!res.ok) {
    throw new Error(`${res.status}: ${await res.text()}`);
  }

  return (await res.json<PokeInterface>()).sprites.front_default;
};

export default function App() {
  const [text, setText] = useState<string>("");
  const [image, setImage] = useState<string>(""); // initial value

  const handleText = (text: string) => {
    setText(text);
  };

  useEffect(() => {
    if (text) {
      getPokemonImage(text)
        .then(setImage)
        .catch(err => {
          console.error("getPokemonImage", err)
          // show an error message or something
        });
    }
  }, [ text ]); // only run on text change