diff --git a/README.md b/README.md new file mode 100644 index 0000000..54a04f7 --- /dev/null +++ b/README.md @@ -0,0 +1,194 @@ +# Reactjs Custom Fetch Hooks + +### Usage and Installation +change directory to your `src/ ` and execute the following comand: + +```bash +git clone https://github.com/Newton-Nganga/awesome-react-fetch-hooks.git hooks/ +``` + +Lastly execute this command to clean up the directory: + +```bash +cd hooks/ ; sudo rm -r .git/ +``` + +And vwalaah! you can now import the hooks where you need them. + +### Preliquisites +- Be using Reactjs or Vite + + +#### Example of useDataFetch hook looks like + +```js + + /* eslint-disable react-hooks/exhaustive-deps */ + /* eslint-disable react-hooks/rules-of-hooks */ + + import { useEffect, useState } from "react"; + + export default function useDataFetch(url, options) { + const opt = options ? options : {}; + const [responseData, setResponseData] = useState(null); + const [error, setError] = useState(null); + const [isLoading, setLoading] = useState(false); + + const fetchData = async () => { + setLoading(true); + + try { + const response = await fetch(url, { + ...opt, + method: "GET", + headers: { + "Content-Type": "application/json", + "Accept": "application/json", + ...opt?.headers, + }, + }); + const data = await response.json(); + setResponseData(data); + } catch (error) { + setError(error); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchData(); + }, [url, options]); + + const refetch = () => { + fetchData(); + }; + + return { responseData, error, isLoading, refetch }; + } +``` +### Get Started +After initializing the hook into your app +#### Importing the Hook + +```js + import useDataFetch from "hooks/useDataFetch"; +``` + +#### Setting up the URL and Options +Define the URL for the API endpoint and any necessary options for the fetch request. + +```js + + const url = "http://localhost:8080/api/data"; + + const options = { + headers: { + "Content-Type": "application/json", + "Authorization": "Bearer wsvhvccmnm" + } + }; + +``` + +### Order of Handling the Returned items +- Handle Loading State First +- Handle Errors +- Display or Use Data + +### Handling Loading State +Check if the loading state is active and display a loading indicator. + +```js + + if (isLoading) { + //do sth incase resource is still loading.. + return
Loading...
; + } +``` +### Handling Errors +Check if an error occurred and handle it accordingly. + +```js + //do sth incase an error is caught ... + if (error) { + return
Error: {error.message}
; + } +``` + + +#### Displaying Data +If loading is complete and no errors occurred, display the fetched data. + +```js + //do sth when the action is complete + return ( + <> + {responseData && responseData.map((item) => ( +
{item.name}
+ ))} + + ); +``` + + +### sample complete usage of the hooks + +```js + import React from "react"; + import useUpdateData from "hooks/useUpdateData"; + + const DataUpdatingComponent = () => { + + const userId="1003" + const url = `http://localhost:8080/api/data/${userId}`; + + //options could be empty but url can't be null/empty + const options = { + headers: { + // "Content-Type": "application/json", --by default this is the set + "Authorization": "Bearer wsvhvccmnm" + } + //...more otions + }; + + const { responseData, error, isLoading, updateData } = useUpdateData(url, options); + //your handle update function + const handleUpdate = () => { + const updatedData = { + // the data/ fields you want to update + name:"John" + email: "john@email.js" + }; + //call the upData method from the hook and pass in the updated data object + updateData(updatedData); + }; + //handle loading state + if (isLoading) { + return
Loading...
; + } + //handle an error if its caught + if (error) { + return
Error: {error.message}
; + } + //do sth with the responseData returned + if(responseData.status.ok){ + toast.success("item updated successfully") + } + return ( + <> + //the rest of the app + + // the rest of the app + + ); + }; + + export default DataUpdatingComponent; +``` + + + +#### Created By + +created by [Newton]("https://github.com/Newton-Nganga/") for reusability. \ No newline at end of file diff --git a/useDataCreate.jsx b/useDataCreate.jsx new file mode 100644 index 0000000..d05f771 --- /dev/null +++ b/useDataCreate.jsx @@ -0,0 +1,35 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable react-hooks/rules-of-hooks */ + +import { useState } from "react"; + +export default function useCreateData(url, options) { + const [data, setData] = useState(null); + const [error, setError] = useState(null); + const [isLoading, setLoading] = useState(false); + + const createData = async (newData) => { + setLoading(true); + + try { + const response = await fetch(url, { + ...options, + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + }, + body: JSON.stringify(newData), + }); + + const result = await response.json(); + setData(result); + } catch (error) { + setError(error); + } finally { + setLoading(false); + } + }; + + return { data, error, isLoading, createData }; +} diff --git a/useDataDelete.jsx b/useDataDelete.jsx new file mode 100644 index 0000000..58a605d --- /dev/null +++ b/useDataDelete.jsx @@ -0,0 +1,36 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable react-hooks/rules-of-hooks */ + +import { useState } from "react"; + +export default function useDeleteData(url, options) { + const opt = options ? options : {} + const [responseData, setResponseData] = useState(null); + const [error, setError] = useState(null); + const [isLoading, setLoading] = useState(false); + + + const deleteData = async () => { + setLoading(true); + + try { + const response = await fetch(url, { + ...opt, + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + ...opt?.headers, + }, + }); + + const result = await response.json(); + setResponseData(result); + } catch (error) { + setError(error); + } finally { + setLoading(false); + } + }; + + return { responseData, error, isLoading, deleteData }; +} diff --git a/useDataFetch.jsx b/useDataFetch.jsx new file mode 100644 index 0000000..d06d28e --- /dev/null +++ b/useDataFetch.jsx @@ -0,0 +1,43 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable react-hooks/rules-of-hooks */ + +import { useEffect, useState } from "react"; + +export default function useDataFetch(url, options) { + const opt = options ? options : {} + const [responseData, setResponseData] = useState(null); + const [error, setError] = useState(null); + const [isLoading, setLoading] = useState(false); + + const fetchData = async () => { + setLoading(true); + + try { + const response = await fetch(url, { + ...opt, + method:"GET", + headers:{ + 'Content-Type': 'application/json', + 'Accept': 'application/json', + ...opt?.headers, + } + }); + const data = await response.json(); + setResponseData(data); + } catch (error) { + setError(error); + } finally { + setLoading(false); + } + }; + + useEffect(() => { + fetchData(); + }, [url, options]); + + const refetch = () => { + fetchData(); + }; + + return { responseData, error, isLoading, refetch }; +} diff --git a/useDataPatch.jsx b/useDataPatch.jsx new file mode 100644 index 0000000..bcb032e --- /dev/null +++ b/useDataPatch.jsx @@ -0,0 +1,37 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable react-hooks/rules-of-hooks */ + +import { useState } from "react"; + +export default function useUpdateData(url,options) { + const opt = options ? options : {} + + const [responseData, setresponseData] = useState(null); + const [error, setError] = useState(null); + const [isLoading, setLoading] = useState(false); + + const patchData = async (patchedData) => { + setLoading(true); + + try { + const response = await fetch(url, { + ...opt, + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + ...opt?.headers, + }, + body: JSON.stringify(patchedData), + }); + + const result = await response.json(); + setresponseData(result); + } catch (error) { + setError(error); + } finally { + setLoading(false); + } + }; + + return { responseData, error, isLoading, patchData }; +} diff --git a/useDataUpdate.jsx b/useDataUpdate.jsx new file mode 100644 index 0000000..dc377c3 --- /dev/null +++ b/useDataUpdate.jsx @@ -0,0 +1,37 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +/* eslint-disable react-hooks/rules-of-hooks */ + +import { useState } from "react"; + +export default function useUpdateData(url,options) { + const opt = options ? options : {} + + const [responseData, setresponseData] = useState(null); + const [error, setError] = useState(null); + const [isLoading, setLoading] = useState(false); + + const updateData = async (updatedData) => { + setLoading(true); + + try { + const response = await fetch(url, { + ...opt, + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + ...opt?.headers, + }, + body: JSON.stringify(updatedData), + }); + + const result = await response.json(); + setresponseData(result); + } catch (error) { + setError(error); + } finally { + setLoading(false); + } + }; + + return { responseData, error, isLoading, updateData }; +}