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

@sonofjs/use-async

v1.1.0

Published

*useReducer* hook's extension to manage asynchronous actions over application's state through http requests.

Downloads

2

Readme

npm Build Status Coverage Status MIT license

useAsync

useReducer hook's extension to manage asynchronous actions over application's state through http requests.

Use case

useReducer hook is very useful for managing application's state, but... What about if you want to integrate http requests on the state's actions? useAsync hook allows you to manage it in an easy way.

How?

Specify an http client with get, post, put and delete methods through the ClientStore. You can use axios, fetch or any other http client. See Client Store.

Define an actions object with this pattern for the common actions:

const actions = {
  ...
  ACTION_TYPE: (state, payload) => ({
    ...state,
    data: payload
  }),
  ASYNC_ACTION: (state) => ({
    ...state,
    request: {
      method: 'GET',
      url: '/api/data'
    }
  })
  ...
}

Note: reducers are commonly defined through switch statements. Author's preference is to use always objects instead of those.

The request key in the ASYNC_ACTION type indicates this action is asynchronous. In this example, the client agent will execute a get http call to the url /api/data. Optionally, to manage the state when the request has been successfully executed add an action with the same type followed by _SUCCESS; and to manage the state when the request has failed add an action with the same type followed by _ERROR. See Actions, Dispatches and State.

Then, you only have to pass this actions objet to the useAsync hook.

const [state, dispatch] = useAsync(actions, initialState)

Note: You can specify an optional initial state as a second argument. The default one is an empty object.

Installation

npm install --save @sonofjs/use-async

Usage

This is a very simple example showing how to use the useAsync hook.

  • axios is used as client agent
  • Example action types:
    • FETCH_DATA: dispatched on the useEffecthook of Component. It has a request key in the output of the action, which indicates the client agent that should make an http request.
    • FETCH_DATA_SUCCESS: will be dispatched if the http call throwed through the FETCH_DATA action has been successfully executed.
    • FETCH_DATA_ERROR: will be dispatched if the http call throwed through the FETCH_DATA action has failed.
    • CREATE: dispatched on the button click event. Will throw an http POST request.
    • CREATE_SUCCESS: will be dispatched if the http call throwed through the CREATE action has been successfully executed.
    • CREATE: will be dispatched if the http call throwed through the CREATE action has failed.
    • UPDATE: will throw an http PUT request.
    • DELETE: will throw an http DELETE request.

Note: the *_SUCCESS and *_ERROR actions are optionals.

Client store

Specify the client agent through the ClientStore.

import React from 'react'

import { ClientStore } from '@sonofjs/use-async'
import axios from 'axios'

import Component from './Component.jsx'

const ViewContainer = () => (
  <ClientStore.Provider agent={axios}>
    <Component />
  </ClientStore.Provider>
)

export default ViewContainer

Actions, dispatches and state

Define the state actions and use the useAsync hook to manage it.

import React, { useEffect } from 'react'
import useAsync from '@sonofjs/use-async'

const actions = {
  FETCH_DATA: (state) => ({
    ...state,
    loading: true,
    request: {
      method: 'GET',
      url: '/api/data'
    }
  }),
  FETCH_DATA_SUCCESS: (state, response) => ({
    ...state,
    loading: false,
    data: response
  }),
  FETCH_DATA_ERROR: (state, error) => ({
    ...state,
    loading: false,
    error
  }),
  CREATE: (state, payload) => ({
    ...state,
    request: {
      method: 'POST',
      url: '/api/data',
      body: payload
    }
  }),
  CREATE_SUCCESS: (state, response) => ({
    ...state,
    data: response
  }),
  CREATE_ERROR: (state, error) => ({
    ...state,
    error
  }),
  UPDATE: (state, payload) => ({
    ...state,
    request: {
      method: 'PUT',
      url: '/api/data',
      body: payload
    }
  }),
  DELETE: (state, payload) => ({
    ...state,
    request: {
      method: 'DELETE',
      url: '/api/data',
      body: payload
    }
  })
}

const initialState = {
  loading: false,
  data: {}
}

const Component = () => {
  const [state, dispatch] = useAsync(actions, initialState)

  useEffect(() => {
    dispatch({ type: 'FETCH_DATA' })
  }, [])

  const create = () => dispatch({ type: 'CREATE', payload: { name: '::name::' } })

  return (
    <>
      {state.loading ? <span>Loading...</span> : null}
      {<span>{JSON.stringify(state.data)}</span>}
      {state.error ? <span>Error: {JSON.stringify(state.error)}</span> : null}
      <button onClick={create}>Create</button>
    </>
  )
}

export default Component

Custom client agent

Interceptors and other methods can be used meanwhile the client agent is used by the asyncAction hook. To connect the client to the store and use its state data implement a method named connect in your client.

/* Your client agent */
import axios from 'axios'

const client = axios.create({
  baseURL: '/api',
  responseType: 'json'
})

const setToken = (config, { store = {} }) => {
  const { token } = store
  if (!token) return

  config.headers.Authorization = `Token ${token}`
}

client.interceptors.request.use(config => {
  setToken(config, client)
  return config
})

client.connect = ({ state: { token } }) => {
  client.store = { token }
}

export default client

...

/* Use of ClientStore */
import React from 'react'

import { ClientStore } from 'use-async'
import clientAgent from './clientAgent'

import Component from './Component.jsx'

const ViewContainer = () => (
  <ClientStore.Provider agent={clientAgent}>
    <Component />
  </ClientStore.Provider>
)

export default ViewContainer

The connect method will be fired on every state change.

Contributing

Contributions welcome; Please submit all pull requests the against master branch. If your pull request contains JavaScript patches or features, you should include relevant unit tests. Please check the Contributing Guidelines for more details. Thanks!

Author

Albert Pérez Farrés

License

  • MIT : http://opensource.org/licenses/MIT