Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am working on this project in React JS where I fetch data from this API URL for my frontend development.

I have made my custom hooks to fetch the data into several files following this medium article as follows:

useApiResult.js

import { useState, useEffect } from "react";

export const useApiResult = (request) => {
  const [results, setResults] = useState(null);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(request)
      .then(async (response) => {
        if (response.ok) {
          setResults(await response.json());
          setError(null);
        } else {
          setError(await response.text())
        }
      })
      .catch((err) => {
        setError(err.message);
      });
  }, [request]);

  return [results, error];
};

useImages.js

import { useMemo } from "react";
import { useApiResult } from "./useApiResult";

const BASE_URL = "http://api.vidyarajkumari.com";
const createUrl = (base, path) => `${base}${path}`;

const getImages = () => [
  createUrl(BASE_URL, "/images/"),
  {
      method: "GET",
  }
];

export const useImages = () => {
  const request = useMemo(() => getImages(), []);
  return useApiResult(request);
}

React component: Images.js

import React from "react";
import { useImages } from "../../hooks/useImages";

export default function Images() {
  const [images, error] = useImages();
  //console.log(images);
  //console.log(error);
  return (
    <>
      <div className="row">
        {
          images.map((item, index) => {
            <div key={index} className="col-md-4 animate-box">
            ...
            // Rest of code goes here
          }
        }
      </>
    </>
  )
}

The problem is that I am unable to get the data in the Images.js component from the useImages hook. The console.log values of images return null. This has been bugging me for a while now and I would greatly appreciate a solution to this. What am I doing wrong here and how can I work around this?

P.S. The API Url is live; so feel free to reference it. Thank you for your time.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
248 views
Welcome To Ask or Share your Answers For Others

1 Answer

I Have a better way to do this using useReducer and custom hook, check this:

By the way, I think your API URL has some problems! (I added input for fetching another URL for test)

const IMAGE_URL = "http://api.vidyarajkumari.com/images/";

const initialState = { loading: true };

function fetchReducer(state, action) {
  switch (action.type) {
    case "fetch":
      return {
        ...state,
        error: undefined,
        loading: true,
      };

    case "data":
      return {
        ...state,
        data: action.data,
        loading: false,
      };

    case "error":
      return {
        ...state,
        error: "Error fetching data. Try again",
        loading: false,
      };

    default:
      return state;
  }
}

function useFetch(url) {
  const [state, dispatch] = React.useReducer(fetchReducer, initialState);
  
  React.useEffect(() => {
    dispatch({ type: "fetch" });

    fetch(url, {
      headers: {
        accept: "application/json",
      },
    })
      .then((res) => res.json())
      .then((data) => dispatch({ type: "data", data }))
      .catch((e) => {
        console.warn(e.message);
        dispatch({ type: "error" });
      });
  }, [url]);

  return {
    loading: state.loading,
    data: state.data,
    error: state.error,
  };
}

function FetchComponent({url}) {
  const { loading, data, error } = useFetch(url);
  console.log(data);
  if (loading) {
    return <p>Fetching {url}...</p>;
  }
  if (error) {
    return <p>{error}</p>
  }
  return <div>{JSON.stringify(data)}</div>
}

const App = () => {
  const [url, setUlr] = React.useState(IMAGE_URL)
  const inputEl = React.useRef(null);
  const changeUrl = () => setUlr(inputEl.current.value)
  return (
    <React.Fragment>
      <input defaultValue="https://icanhazdadjoke.com/" ref={inputEl} type="text" />
      <button onClick={changeUrl}>Fetch</button>
      {url && <FetchComponent url={url}/>}
    </React.Fragment>
  )
}

ReactDOM.render(<App/>, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...