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



我刚开始使用原生react,无法使用此api,当我在浏览器中启动此应用程序时,它运行良好,但当我进入expo应用程序时它不会显示pokemon图像,有人能帮我吗?

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
}
});

您当前的代码会导致一个无限循环。。。

  1. 您键入一些触发searchApi(text)的文本
  2. 写入触发效果挂钩的response
  3. 因为text仍然真实,所以它再次触发searchApi(text)
  4. 转到#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
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,
},
});

最新更新