1.1.9 • Published 3 years ago

use-api-action v1.1.9

Weekly downloads
30
License
MIT
Repository
github
Last release
3 years ago

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
    }
    FieldDescription
    dataThe response data returned by your API after a success
    errorsThe response errors returned by your API after an error
    failedThe failure status. It is true if there was an error when fetching data
    submittingSet to true when the data is being fetched
    submittedSet to true when the data has been fetched whether there was an error or not
    statusCodeUpdated after every successful / failed request
    fetchedSet to true when the data has been fetched only when there was no error.
    fetchingSimilar 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

1.1.9

3 years ago

1.1.8

3 years ago

1.1.7

3 years ago

1.1.6

3 years ago

1.1.5

3 years ago

1.1.4

3 years ago

1.1.3

3 years ago

1.1.2

3 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.0

3 years ago