React Native render error: null is not an object (evaluating origin.location)

React Native render error: null is not an object (evaluating origin.location)

我是 react-native 的新手,决定按照教程尝试克隆一个应用程序。我正在尝试将存储在 redux 中的数据传递到在我的主屏幕上呈现的地图,但是当我 运行 时,我不断收到以下错误:null 不是一个对象(评估 origin.location)。欢迎任何建议、解决方案和快速修复。谢谢

主屏幕代码


    import { View, TouchableOpacity, Text } from 'react-native'
    import { React } from 'react'
    import HeaderTabs from '../components/HeaderTabs'
    import { GooglePlacesAutocomplete } from 'react-native-google-places-autocomplete'
    import { Ionicons } from '@expo/vector-icons'
    import { setDestination, setOrigin } from '../slices/navSlice'
    import { useDispatch } from 'react-redux'
    import { SafeAreaView } from 'react-native-safe-area-context'
    import { GOOGLE_MAPS_APIKEY } from '@env'
    import Map from './components/Map'
    
    const Home = ({navigation}) =>{
      const dispatch = useDispatch();
    
      return (
          <SafeAreaView style={{ backgroundColor:"white", 
                          flex:1,
                          padding:5, 
                          marginTop:-20
                          }}> 
                          
              <View style={{alignItems:"flex-end"}} >
                <TouchableOpacity onPress={() => {navigation.navigate("CustomerInfo")}}>
                  <Ionicons name="person-circle" size={30} color="black" />
                </TouchableOpacity>
              </View>
    
                <HeaderTabs />
    
                <View style={{marginTop:15, flexDirection:"row"}}>
                  
                  <GooglePlacesAutocomplete
                  query={{key: GOOGLE_MAPS_APIKEY}}
                  enablePoweredByContainer={false}
                  onPress={(data, details = null) => {
                    dispatch(setOrigin({
                      location: details.geometry.location,
                      description: data.description,
                    })
                    ); 
    
                    dispatch(setDestination(null));
                    }}
                  fetchDetails={true}
                  returnKeyType={"search"}
                  placeholder='Enter package pickup location' 
                  debounce={400}
                  nearbyPlacesAPI='GooglePlacesSearch'
                  styles={{
                      textInput:{
                          backgroundColor:"#eee",
                          borderRadius:15,
                          fontFamily:"Poppins_500Medium",
                          marginTop:10,
                          fontSize:18,
                      },
    
                      textInputContainer:{
                          backgroundColor:"#eee",
                          borderRadius:15,
                          flexDirection:"row",
                          alignItems:"center",
                          width:380
                      },
                  }}
    
                  renderLeftButton={() => (
                      <View style={{
                        marginLeft:10
                      }}>
                        <Ionicons name="location" size={20} color="green" />
                      </View>
                  )}
                  renderRightButton={() => (
                      <View style={{
                        flexDirection:"row",
                        marginRight:5,
                        backgroundColor:"white",
                        padding:9,
                        borderRadius:30,
                        alignItems:"center"
                      }}>
                        <Ionicons name="search" size={15} color="black" />
                      </View>
                  )}     
                  />
            </View>
            
            <Map />
    
          </SafeAreaView>      
        
      )};
    
      export default Home;

地图组件代码


    import { View, Text } from 'react-native'
    import React from 'react'
    import MapView, { Marker } from 'react-native-maps'
    import { useSelector } from 'react-redux'
    import { selectOrigin } from '../slices/navSlice'
    
    const Map = () => {
        const origin = useSelector(selectOrigin);
    
      return (
        <MapView
            style={{flex:1, marginTop:10}}
            initialRegion={{
                latitude: origin.location.lat,
                longitude: origin.location.lng,
                latitudeDelta: 0.0922,
                longitudeDelta: 0.0421,
            }}
            />
      );
    };
    
    export default Map;

origin.location 来自哪里


const initialState = {
    origin: null,
    destination: null,
    travelTimeInformation: null
}

export const navSlice = createSlice({
    name: "nav",
    initialState,
    reducer: {
        setOrigin: (state, action) => {
            state.origin = action.payload; 
        },
        setDestination: (state, action) => {
            state.destination = action.payload; 
        },
        setTravelTimeInformation: (state, action) => {
            state.travelTimeInformation = action.payload; 
        },
    },
});

export const { setOrigin, setDestination, setTravelTimeInformation } = navSlice.actions;

export const selectOrigin = (state) => state.nav.origin;
export const selectDestination = (state) => state.nav.destination;
export const selectTravelTimeInformation = (state) => state.nav.travelTimeInformation;

export default navSlice.reducer;

问题

origin状态值初始为null

const initialState = {
  origin: null, // <-- initially null here
  destination: null,
  travelTimeInformation: null
}

并且代码正在尝试访问此空值。

const Map = () => {
  const origin = useSelector(selectOrigin);

  return (
    <MapView
      style={{flex:1, marginTop:10}}
      initialRegion={{
        latitude: origin.location.lat,
        longitude: origin.location.lng,
        latitudeDelta: 0.0922,
        longitudeDelta: 0.0421,
      }}
    />
  );
};

解决方案

你有几个选择。这里有4个,可能还有其他的。

  1. 有条件地在正在填充的 origin 状态上呈现 MapView 组件。

    const Map = () => {
      const origin = useSelector(selectOrigin);
    
      return origin?.location
        ? (
          <MapView
            style={{flex:1, marginTop:10}}
            initialRegion={{
              latitude: origin.location.lat,
              longitude: origin.location.lng,
              latitudeDelta: 0.0922,
              longitudeDelta: 0.0421,
            }}
          />
        ) : null;
    };
    
  2. origin 访问上使用可选链接运算符并提供回退值。

    const Map = () => {
      const origin = useSelector(selectOrigin);
    
      return (
        <MapView
          style={{flex:1, marginTop:10}}
          initialRegion={{
            latitude: origin?.location?.lat ?? 0,  // use fallback value that makes sense
            longitude: origin?.location?.lng ?? 0, // use fallback value that makes sense
            latitudeDelta: 0.0922,
            longitudeDelta: 0.0421,
          }}
        />
      );
    };
    
  3. 从选择器中提供一个有效的、已定义的原始值。

    const defaultOrigin = { location: { lat: 0, lng: 0 } }; // use origin value that makes sense
    export const selectOrigin = (state) => state.nav.origin ?? defaultOrigin;
    
  4. 或者只是提供一个更有用的初始状态值。

     const defaultOrigin = { location: { lat: 0, lng: 0 } }; // use origin value that makes sense
     const initialState = {
       origin: defaultOrigin,
       destination: null,
       travelTimeInformation: null
     }