My app returns a "null is not an object" Render Error when consuming the useFetch custom hook that I made to get async data using axios . The status , error , and data properties remains the same with their default values, I don't know if the problem is related to how I mutate my data or I'm not returning or consuming them properly.
// Axios config
import axios from "axios";
const instance = axios.create({
baseURL: "http://10.0.2.2:8000/api",
});
export default instance;
// Custom hook
import { useReducer, useEffect } from "react";
import axiosConfig from "../axiosConfig";
export default function useFetch(url) {
const initialState = {
status: "idle",
error: null,
data: null,
};
const [state, dispatch] = useReducer((state, action) => {
switch (action.type) {
case "FETCHING":
return { ...state, status: "fetching" };
case "FETCHED":
return { ...state, status: "fetched", data: action.payload };
case "FETCH_ERROR":
return { ...state, status: "error", error: action.payload };
default:
return state;
}
}, initialState);
useEffect(() => {
let cancelRequest = false;
if (!url) return;
function fetchData() {
dispatch({ type: "FETCHING" });
axiosConfig
.get(url)
.then((response) => {
if (cancelRequest) return;
dispatch({ type: "FETCHED", payload: response.data });
})
.catch((error) => {
if (cancelRequest) return;
dispatch({ type: "FETCH_ERROR", payload: error });
});
}
fetchData();
return function cleanup() {
cancelRequest = true;
};
}, [url]);
return [state];
}
// Consume custom hook
import React from "react";
import {
View,
Text,
StyleSheet,
TouchableOpacity,
Image,
ActivityIndicator,
} from "react-native";
import GlobalStyles from "../constants/GlobalStyles";
import { Entypo, EvilIcons } from "@expo/vector-icons";
import format from "date-fns/format";
import useFetch from "../utils/hooks/useFetch";
export default function TweetScreen({ route, navigation }) {
const [{ status, error, data: tweet }] = useFetch(
`/tweets/${route.params.tweetId}`
);
error && console.log(error);
function gotoProfile(userId) {
navigation.navigate("Profile Screen", { userId });
}
return (
<View style={GlobalStyles.container}>
{status === "fetching" ? (
<ActivityIndicator size="large" color="#007aff" />
) : (
<>
<View
style={[
GlobalStyles.flexRow,
GlobalStyles.spaceBetween,
styles.tweetContainer,
]}
>
<TouchableOpacity
style={GlobalStyles.flexRow}
onPress={() => gotoProfile(tweet.user.id)}
>
<Image
style={styles.avatar}
source={{ uri: tweet.user.avatar }}
/>
</TouchableOpacity>
</View>
</>
)}
</View>
);
}
Your data response is null. You can avoid getting undefind by saying { uri : tweet?.data.avatar }
, but I assume you should rather first destructure your useFetch correctly by doing const { data, error , loading } = useFetch(url)
. If thats not going to help, then you should require(`${tweet?.data.avatar}`)
. Hope that helps. Your code is really fragile though, you should debug first why you getting back null...
Just solved this thing, turns out I just needed to do return state
instead of return [state]
as wrapping it inside an array causes the state to be stale.
So now I just consume the custom hook like this: const { status, error, data: tweet } = useFetch(...);
Instead of: const [{ status, error, data: tweet }] = useFetch(...);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.