npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

use-react-api

v2.0.5

Published

This package help you with react http.

Downloads

41

Readme

use-react-api

This package makes http/ws request in react easier.

Features

  • React.Suspense support!
  • Lightweight
  • Auto and manual request
  • Fully customizable
  • Using axios
  • Multiple instance

Installation

  • with npm
npm i use-react-api axios
  • with yarn
yarn add use-react-api axios
  • with pnpm
pnpm add use-react-api axios

Setup

Configure your application with whatever configuration you want.

Basic Usage:

/* api.js */

import ReactApi from 'use-react-api'
const reactApi = ReactApi()

export default reactApi
export const { useApiOnce, useApi, useDataApi, createUseSuspense } =
  reactApi.hooks

/* Compontnt.js */

import { useApiOnce } from './api.js'

const Component = () => {
  const api = useApiOnce({ get: 'https://www.boredapi.com/api/activity' })

  if (api.error) return <div>{api.error}</div>
  if (api.loading) return <div>'Loading...'</div>
  return <div>{api.data.activity}</div>
}
import { useState } from 'react'
import { useApi } from './api.js'

const Component = () => {
  const [msg, setMsg] = useState()
  const api = useApi()

  const handleClick = async () => {
    const { data, ok } = await api.get('https://www.boredapi.com/api/activity')
    if (ok) {
      setMsg(data.activity)
    }
  }

  if (api.error) return <div>{api.error}</div>
  if (api.loading) return <div>'Loading...'</div>
  return (
    <button onClick={handleClick}>{msg ?? 'Click me to get message'}</button>
  )
}

Advanced usages of ReactApi:

ReactApi(AxiosInstanceConfig, ReactApiConfig)
// { instance, methods, useApi, useApiOnce, createSuspenseApi }

Check Axios instance config for AxiosInstanceConfig

ReactApiConfig options:

{
  _getSuccess?: (response: AxiosResponse) => any
  getSuccess?: (response: AxiosResponse) => any
  _getFail?: (err: AxiosError) => void
  getFail?: (err: AxiosError) => void
}

Option _getSuccess & _getFail:

These are middleware. When a request succeed this function is called, After finishing this function getSuccess | getFail starts.

Option getSuccess && getFail:

This gives AxiosResponse or AxiosError as first argument and send the returned value.

Example:

ReactApi(
  {},
  {
    _getSuccess: (response) => {
      console.log('Raw response', response)
    },
    getSuccess: (response) => {
      return response.status === 204
        ? true
        : response.data?.data ?? response.data
    },

    _getFail: (err) => {
      console.log('Raw error', err)
    },
    getFail: (err) => {
      return err.response?.data?.message ?? err.message
    },
  }
)

ReactApi() API:

This returns:

{
  methods: {…},
  hooks: {…},
  axiosInstance: ƒ
}

ReactApi().axiosInstance:

This is just the raw Axios instance

ReactApi().methods:

This is an object:

{
  requests: async Function,
  request: async Function,
  get: async Function,
  delete: async Function,
  head: async Function,
  options: async Function,
  post: async Function,
  put: async Function,
  patch: async Function,
}

All the functions takes axios params, check Axios instance config for more details. And they return {error, data, ok}

ReactApi().hooks.useApi(config):

Usages:

import { useState } from 'react'
import { useApi, useDataApi } from './api.js'

const Component = () => {
  const [msg, setMsg] = useState()

  // For normal usages
  const api = useApi()

  // When you don't want to use manual loading component, Just the React.Suspense
  const api = useApi({ suspense: true })

  // If you use this you don't need to set the data to a state. `api.data` will be the data from response
  const api = useDataApi({ suspense: true })

  const handleClick = async () => {
    const { data, ok } = await api.get('https://www.boredapi.com/api/activity')
    if (ok) {
      setMsg(data.activity)
    }
  }

  if (api.error) return <div>{api.error}</div>
  if (api.loading) return <div>'Loading...'</div>
  return (
    <button onClick={handleClick}>{msg ?? 'Click me to get message'}</button>
  )
}

The returned value looks like:

{
  loading: Boolean,
  data: Boolean,
  error: Boolean,

  requests: async Function,
  request: async Function,
  get: async Function,
  delete: async Function,
  head: async Function,
  options: async Function,
  post: async Function,
  put: async Function,
  patch: async Function,

  status: {
    loading: Boolean,
    data: Boolean,
    error: Boolean,
  },

  setStatus: {
    loading: Function, // Set custom loading status
    data: Function, // Set custom data status
    error: Function, // Set custom error status
    reset: Function // Reset status
  },

  methods: {
    request: async Function,
    get: async Function,
    delete: async Function,
    head: async Function,
    options: async Function,
    post: async Function,
    put: async Function,
    patch: async Function,
  }
}

These axios methods the returned value from getSuccess when there is no error else returns undefined

ReactApi().hooks.useApiOnce(...axios, onLoad):

import { useApiOnce } from './api.js'

const Component = () => {
  // Basic usages
  const api = useApiOnce({ get: 'https://www.boredapi.com/api/activity' })

  // With a function
  const api = useApiOnce(
    { get: 'https://www.boredapi.com/api/activity' },
    ([res]) => {
      console.log(res.data)
    }
  )

  if (api.error) return <div>{api.error}</div>
  if (api.loading) return <div>'Loading...'</div>
  return <div>{api.data.activity}</div>
}

The returned value looks like:

{
  loading: Boolean,
  data: T[],
  error: T[],

  retry: Function, // Retry the request

  status: {
    loading: Boolean,
    data: T[],
    error: T[]
  },

  setStatus: {
    loading: Function, // Set custom loading status
    data: Function, // Set custom data status
    error: Function, // Set custom error status
    reset: Function // Reset status
  }
}

ReactApi().hooks.createSuspense():

This function returns a hook that uses React.Suspense.

!! Warning !! -- Do not use this hook multiple times. Create a new hook for each component

import { createSuspense } from './api.js'
const useSuspenseApi = createSuspense()
const useSuspenseApi2 = createSuspense({ cache: true })

const Component = () => {
  // Basic usages
  const [bored, dummy] = useSuspenseApi(
    {url: 'https://www.boredapi.com/api/activity'}
    {url: 'https://dummyjson.com/products'}
  )

  // With a function
  const api2 = useSuspenseApi2(
    {url: 'https://www.boredapi.com/api/activity'}
    {url: 'https://dummyjson.com/products'}
    ([bored, dummy]) => {
      // This onLoad function will be called just once when the data loads for the first time
      console.log(bored.data, dummy.data)
    }
  )

  return <div>{bored.data.activity}</div>
}

What about AbortController?

I think it will be performence costly if a add it with everything. But there is an option.

import { useSignal } from 'use-react-api'
import { useApi } from './api.js'

const Component = () => {
  const api = useApi()
  const [signal, abort, isActive] = useAbortSignal()

  const handleSearch = async (e) => {
    const res = await api.get('/user/search', {
      signal: signal(),
    })
  }
}

Wait a min, what about WebSocket?

/* ws.js */

import { ReactWs } from 'use-react-api'
import { io } from 'socket.io-client'

const socket = io('http://localhost:8000')

socket.on('connect', () => {
  console.log('connected')
})

export const { useWs, useDataWs } = ReactWs(socket, {
  checkData(res) {
    return res.status === 'success'
  },
  formatData(res) {
    return res.data ?? res
  },
  formatError(res) {
    return res.message ?? res
  },
})

/* App.js */

import { useWs, useDataWs } from './ws'

const App = () => {
  const ws = useWs({ suspense: true })
  const ws = useDataWs({ suspense: true })

  const handleClick = async () => {
    // this is just like useApi().request but in socket way!
    const res = await ws.emit('hello')
    console.log(res)
  }

  const handleClick = async () => {
    // this is just like useApi().requests
    const [res1, res2] = await ws.emitAll('hello')
    console.log(res1, res2)
  }

  return <button onClick={handleClick}>Click</button>
}

Made by Nazmus Sayad with ❤️.