React Native: _this.setState不是在react-navigation应用中抛出的函数



我有一个React应用程序在博览会小吃工作,但需要添加导航。当我这样做的时候,我得到了这个。setState不是一个函数。任何帮助是非常感激的,因为这是相当新的我。没有导航,并利用导出默认类App extends Component,应用程序构建和运行应该,但我有麻烦弄清楚在哪里/如何声明setState。

代码如下:

import React, { useEffect, useState } from 'react';
import { View, ActivityIndicator, Text,SafeAreaView,FlatList,ImageBackground,Image,StyleSheet,TouchableOpacity } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import MapView, { Marker } from "react-native-maps";
import axios from 'axios';
const GOOGLE_MAPS_APIKEY = "xxxxxxxx";

function HomeScreen() {

const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const state  = { reports: [] }

const mapMarkers = () =>  {
return state.reports.map((report) => <Marker
key={report.anum}
coordinate={{ latitude: report.lat, longitude: report.lon }}
title={report.name}
description={report.image}
>
</Marker >)
}

const getMovies = async () => {
fetch('https://xxxxx.cfm?d3d2fcs1d')
.then(res => res.json())
.then(data => {
this.setState({reports: data.reports}, () =>  {
console.log(data)
}

)})
.catch(console.error)

}

getMovies()
return (
<View style={styles.container}>

<MapView
style={{ ...StyleSheet.absoluteFillObject }}
initialRegion={{
latitude: 34.8527370,
longitude: -82.3933179,
latitudeDelta: .01,
longitudeDelta: .01
}}  apikey={GOOGLE_MAPS_APIKEY} >
{mapMarkers()}
</MapView>
</View>
);

}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} options={{headerShown: false}}/>
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
  MainContainer: {
    justifyContent: 'center',
    flex: 1,
    paddingTop: 50,
backgroundColor: '#000',
  },
  logo: {
    width: '90%',
    height: 159,
    marginTop: 4,
    justifyContent: 'center',
  },
  bannerAd: {
    width: '100%',
    height: 80,
    marginBottom: 12,
    justifyContent: 'center',
backgroundColor: '#000',
  },
  imageThumbnail: {
    justifyContent: 'center',
    alignItems: 'center',
    height: 100,
  },
});
export default App;

你有一个功能组件,所以不应该使用setState。

你已经有一个钩子来存储你的数据,你应该更新setData,在你现在试图使用状态的地方,使用钩子中的数据代替。(const [data, setData] = useState([]);)另一件事,你调用getMovies()的方式将在每次渲染时发生。通常对于异步数据获取,你想使用一个useEffect钩子。您可能希望在挂载时发生这种情况,并且您还应该进行清理,以防组件在调用完成之前被卸载。

useEffect(() => {
let controller = new AbortController();
(async () => {
try {
const response = await fetch('https://xxxxx.cfm?d3d2fcs1d', {
signal: controller.signal
});
const data = response.json();
setData(data.reports);
controller = null;
} catch (e) { 
// Handle fetch error
}
})();
return () => controller?.abort();
}, []);

我知道你可能混淆了React功能组件和React类组件。如果你决定将React组件声明为函数,那么你可以使用像useState这样的React Hooks。但是如果你宁愿选择类组件,那么你可以使用this.statethis.setState,因为没有React Hooks

要修复这些不匹配,您的代码应该像这样:

import React, { useEffect, useState } from 'react';
import {
View,
ActivityIndicator,
Text,
SafeAreaView,
FlatList,
ImageBackground,
Image,
StyleSheet,
TouchableOpacity,
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import MapView, { Marker } from 'react-native-maps';
import axios from 'axios';
const GOOGLE_MAPS_APIKEY = 'xxxxxxxx';
function HomeScreen() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
// EDIT 1:  Add react state hook to manage reports
const [reports, setReports] = useState([]);

// EDIT 3: only fetch movies once the screen loaded and not every time it renders
useEffect(() => {
// EDIT 4: run getMovies() asynchronously
(async () => { 
await getMovies(); 
})(); 
}, []);
const mapMarkers = () => {
return reports.map((report) => (
<Marker
key={report.anum}
coordinate={{ latitude: report.lat, longitude: report.lon }}
title={report.name}
description={report.image}
></Marker>
));
};
const getMovies = async () => {
fetch('https://xxxxx.cfm?d3d2fcs1d')
.then((res) => res.json())
.then((data) => {
//  EDIT 2: Update reports state
setReports(data.reports, () => {
console.log(data);
});
})
.catch(console.error);
};
return (
<View style={styles.container}>
<MapView
style={{ ...StyleSheet.absoluteFillObject }}
initialRegion={{
latitude: 34.852737,
longitude: -82.3933179,
latitudeDelta: 0.01,
longitudeDelta: 0.01,
}}
apikey={GOOGLE_MAPS_APIKEY}
>
{mapMarkers()}
</MapView>
</View>
);
}
function DetailsScreen() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Details Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} options={{ headerShown: false }} />
<Stack.Screen name="Details" component={DetailsScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
MainContainer: {
justifyContent: 'center',
flex: 1,
paddingTop: 50,
backgroundColor: '#000',
},
logo: {
width: '90%',
height: 159,
marginTop: 4,
justifyContent: 'center',
},
bannerAd: {
width: '100%',
height: 80,
marginBottom: 12,
justifyContent: 'center',
backgroundColor: '#000',
},
imageThumbnail: {
justifyContent: 'center',
alignItems: 'center',
height: 100,
},
});
export default App;

编辑1:andEDIT 2:应该足够了。

现在,为了避免在屏幕加载时出现循环,总是建议不要在主渲染函数中更新状态。所以我添加了EDIT 3:解决这个问题。

此外看看反应钩子:https://reactjs.org/docs/hooks-state.html

最新更新