我有一个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.state
或this.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