redux-act-async-api v1.2.0
redux async api
base on react-act
USEAGE
install: npm i redux-act-async-api
DEMO: to fetch https://cnodejs.org/api/v1/topics?page={{page}}
add redux middlreware
import { createStore, applyMiddleware, combineReducers } from 'redux'
import { apiMiddleware } from 'redux-act-async-api'
import topics from './topics'
const reducers = combineReducers({
topics
})
const middleware = [
apiMiddleware({ API_PREFIX: 'https://cnodejs.org/api/v1' }) // api prefix
]
if (process.env.NODE_ENV !== 'production') {
middleware.push(require('redux-logger')())
}
/*****************************************************************************/
// func createStore `store = createStore(initState)`
export default (initState = {}) => createStore(
reducers,
initState,
applyMiddleware(...middleware)
)
create reducer and actions in one file
import { CALL_API, makeAction, createReducer } from 'redux-act-async-api'
import update from 'react/lib/update'
const HUSSIF = {}
const INITAL = {
fetching: false,
currentPage: 1,
data: []
}
export const fetchTopics = makeAction(HUSSIF, {
type: 'FETCH_TOPICS',
endpoint: '/topics', // https://cnodejs.org/api/v1/topics,
method: 'GET',
request: (state, payload) => update(state, {
fetching: { $set: true }
}),
success: (state, payload) => update(state, {
fetching: { $set: false },
data: { $set: payload.result.data },
currentPage: { $set: payload.query.page }
}),
failure: (state, payload) => update(state, {
fetching: { $set: true }
})
})
export default createReducer(HUSSIF, INITAL)
dispatch action in component
import React from 'react'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import * as actions from 'reducers/topics'
const mapState = state => ({
topics: state.topics.data,
fetching: state.topics.fetching
})
const mapDispatch = dispatch => bindActionCreators(actions, dispatch)
@connect(mapState, mapDispatch)
export default class extends React.Component {
changePage = (p = 0) => {
const { currentPage, fetchTopics } = this.props
const page = currentPage + p
const payload = await fetchTopics({ query: { page } })
console.log({ page, payload })
}
componentDidMount() {
this.changePage()
}
render() {
const { currentPage } = this.props
return (
<div>
<h1>TOPIC LIST</h1>
<ul>{ this.props.topics.map(topic => <li>{ topic.title }</li>) }</ul>
<button disabled={currentPage === 1} onClick={() => this.changePage(-1)}>pre</button>
<button onClick={() => this.changePage(1)}>next</button>
</div>
)
}
}
payload
fn makeAction(HUSSIF, conf) -> fn asyncAction
asyncAction
: function
(body, query) -> Object
{ type, payload }
body
& query
in payload is which user passed
result
in payload is api response
before dispatch request
action fetch(url) -> res
if res.ok
dispatch success
action
else dispatch failure
action
conf.endpoint
: String
conf.method
: String
defualt GET
conf.headers
: Object
default { 'Accept': 'application/json', 'Content-Type': 'application/json' }
it will use to fetch(API_PREFIX + conf.endpoint, { headers: conf.headers, method: conf.method })
conf.request
: function
(state, payload) -> newState
conf.success
: function
(state, payload) -> newState
conf.failure
: function
(state, payload) -> newState
define each api status how state to update.