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-api-action

v1.1.9

Published

REST API services made easy with redux

Downloads

38

Readme

Redux API Actions

Tests GitHub issues GitHub stars GitHub forks GitHub license npm npm npm type definitions NPM

Consume APIs with react/redux without the pain of writing actions and reducers as simple as:

const [login, loginState] = useApiAction(Api, api => api.authentication.login)

Features

  • Redux
  • Multiple APIs support
  • Typescript support
  • React Hooks and Class components

Installation

NPM

npm install --save use-api-action

Yarn

yarn add use-api-action

Basic Usage Guide

Step 1: Create an API definition with the following structure.

An API definition should have groups. Within each group, define the endpoints as shown below. Axios is required for this, as the underlying functionality depends on the AxiosResponse object.

You can use Typescript to define the argument types as you wish.

const testApi = {
  authentication: {
    login: (username, password) => axios.post('/login', { username, password }),
    register: (username, password) => axios.post('/register', { username, password })
  },
  users: {
    list: () => axios.get('/users')
  },
  products: {
    getProduct: productId => axios.get('/products/' + productId)
  }
}

Step 2: Attaching to redux.

Provide the API definition and a name for the API. This name should be unique when defining multiple APIs.

const Api = buildApiReducer(testApi, 'Test')
const Api2 = buildApiReducer(productsApi, 'Products')

Combine your APis into one reducer.

const apis = combineApiReducers({ Api, Api2 })

Register the APIs to your store.

const rootReducer = combineReducers({
  //... your other reducers here. You have to pass apiReducer under 'apis' key
  apis: apis.reducer
})

// Ensure you have registered apis.middleware as well.

const store = createStore(rootReducer, applyMiddleware(apis.middleware))

Step 3: Usage on your component.

You can either use the hook or use Higher Order Components.

1. React Hooks.

const LoginPage = props => {
  const [login, loginState] = useApiAction(Api, api => api.authentication.login)

  return <div></div>
}

2. Class components

class LoginPage extends React.Component {
  render() {
    const [login, loginState] = this.props.login
  }
}

export default connectApi(Api, api => {
  return {
    login: api.authentication.login // Maps "login" to the props.
  }
})(LoginPage)

Step 4: Make use of the actions / states.

class LoginPage extends React.Component {
  render() {
    const [login, loginState] = this.props.login()

    const onSubmit = (username, password) => {
      // Invoking this will automatically pass the arguments to the api definition endpoint.
      login(username, password)
    }

    return loginState.submitting ? <div>Logging in...</div> : <LoginForm onSubmit={onSubmit} />
  }
}

The API action

The api action returns an array with the same structure as the useState react hook. With the following structure.

const [login, loginState, clearLogin] = useApiAction(Api, api => api.authentication.login)
// For class components
const [login, loginState, clearLogin] = props.state.login()
  1. The first element is the actionCreator. It is used to make the api call specified. In this example, you will invoke it with the username and password arguments.

    login('username', 'password')

    It returns the following.

    {
      payload: [],
      onSuccess: (response, payload) => {}
      onError: (error, payload) => {}
      statusCode: 500
      id: "default" // The id can be used to distinguish two separate states to the same API cal 
      clearData: boolean // clear the existing data when the api call made.
      clearErrors: boolean // clear the existing errors when the api call is made.
      errorHandler: (error) => {},
      onNewData?: (prevState, newState) => State
    }
  2. The second argument is the state of the action. It is defined as follows:

    {
      "data": null,
      "errors": null,
      "failed": false,
      "submitting": false,
      "submitted": false,
      "fetching": false,
      "fetched": false,
      "statusCode": 200
    }

    | Field | Description | | :--------- | :--------------------------------------------------------------------------- | | data | The response data returned by your API after a success | | errors | The response errors returned by your API after an error | | failed | The failure status. It is true if there was an error when fetching data | | submitting | Set to true when the data is being fetched | | submitted | Set to true when the data has been fetched whether there was an error or not | | statusCode | Updated after every successful / failed request | | fetched | Set to true when the data has been fetched only when there was no error. | | fetching | Similar to submitting, to show when data is being fetched. |

  3. The third argument is the clear action. It is used to clear the state (data, errors, statusCode etc.) and restore it to the initial state.

    useEffect(() => {
      const { id } = login('username', 'password')
    
      return () => clearLogin(id)
    }, [])

Response Handlers.

You can pass response handlers for both onSuccess and onError to the api action.

// hooks
const [login, loginState] = useApiAction(Api, api => api.authentication.login, {
  onSuccess: (response, payload) => {
    // do something with the response / payload
  },
  onError: (error, payload) => {}
})

// class components
const [login, loginState] = this.props.login({
  onSuccess: (response, payload) => {},
  onError: (error, payload) => {}
})

Handling Data

Clear data before making a new request

You can clear data before making a new api call. By default, the existing data is kept until the api request is successful.

// hooks
const [login, loginState] = useApiAction(Api, api => api.authentication.login, {
  clearData: true
})

// class components
const [login, loginState] = this.props.login({ clearData: true })

Clear errors before making a new request

You can clear the existing errors before making a new api call. By default the existing errors are kept until there are new errors.

// hooks
const [login, loginState] = useApiAction(Api, api => api.authentication.login, {
  clearErrors: true
})

// class components
const [login, loginState] = this.props.login({ clearErrors: true })

Modifying the existing data after a new response.

You can modify the existing state after making a new request

// hooks

const [getStudents, studentList] = useApiAction(Api, api => api.students.list, {
  onNewData: (prevStudents, students) => ([...prevStudents, ...students])
})

const [getStudents, studentList] = this.props.students({
  onNewData: (prevStudents, students) => ([...prevStudents, ...students])
})

License (MIT)

Copyright © Moses Gitau All rights reserved.

Find a copy of the License here