Skip to content

Commit fbccfe1

Browse files
committed
feat: add axios hooks
1 parent 03165d4 commit fbccfe1

11 files changed

+319
-1
lines changed

.babelrc

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"presets": [
3+
"@babel/preset-env",
4+
"@babel/preset-react"
5+
]
6+
}

.eslintrc

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"parser": "babel-eslint",
3+
"env": {
4+
"browser": true,
5+
"node": true
6+
},
7+
"extends": [
8+
"eslint:recommended",
9+
"plugin:react/recommended"
10+
],
11+
"plugins": [
12+
"react-hooks"
13+
],
14+
"rules": {
15+
"react-hooks/rules-of-hooks": "error"
16+
}
17+
}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ bower_components
3131

3232
# Compiled binary addons (https://nodejs.org/api/addons.html)
3333
build/Release
34+
dist
3435

3536
# Dependency directories
3637
node_modules/

README.md

+41-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,42 @@
11
# react-hooks-axios
2-
Custom React Hooks for Axios.js
2+
3+
Custom React Hooks for [Axios.js](https://github.com/axios/axios).
4+
5+
## Usage
6+
7+
>The Hooks isn't stable, the stable release will landing on [Q1 of 2019](https://reactjs.org/blog/2018/11/27/react-16-roadmap.html). Make sure that you install the correct version of `react(>= v16.7.0-alpha)` and `react-dom(>= v16.7.0-alpha)`.
8+
9+
`npm i @use-hooks/axios -S`
10+
11+
```js
12+
import useAxios from '@use-hooks/axios';
13+
14+
function YourComponent() {
15+
const {
16+
// Ref: https://goo.gl/dJ6QcV
17+
response,
18+
loading,
19+
error,
20+
// MANUAL RUN trigger
21+
query,
22+
} = useAxios({
23+
url: 'https://randomuser.me/api/',
24+
method: 'GET',
25+
// Ref: https://goo.gl/UPLqaK
26+
options: {},
27+
// Trigger conditions for AUTO RUN
28+
// trigger,
29+
filter: () => true,
30+
});
31+
32+
// Others...
33+
}
34+
```
35+
36+
See `./example` for a full example.
37+
38+
## License
39+
40+
MIT
41+
42+
> Generated by [create-react-hooks](https://github.com/use-hooks/create-react-hooks).

example/App.js

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React, { useState } from 'react';
2+
3+
import useAxios from '../src';
4+
5+
export default function App() {
6+
const [gender, setGender] = useState('');
7+
const {
8+
response,
9+
loading,
10+
error,
11+
query,
12+
} = useAxios({
13+
url: `https://randomuser.me/api/${gender === 'unknow' ? 'unknow' : ''}`,
14+
method: 'GET',
15+
options: {
16+
params: { gender },
17+
},
18+
trigger: gender,
19+
filter: () => !!gender,
20+
});
21+
22+
const data = (response || {}).data;
23+
24+
const options = [
25+
{ gender: 'female', title: 'Female' },
26+
{ gender: 'male', title: 'Male' },
27+
{ gender: 'unknow', title: 'Unknow' },
28+
];
29+
return (
30+
<div>
31+
{options.map(item => (
32+
<div key={item.gender}>
33+
<input
34+
type="radio"
35+
id={item.gender}
36+
value={item.gender}
37+
checked={gender === item.gender}
38+
onChange={(e) => setGender(e.target.value)}
39+
/>
40+
<label htmlFor={item.gender}>{item.title}</label>
41+
</div>
42+
))}
43+
<button onClick={query}>Refresh</button>
44+
<div>
45+
{loading ? 'loading...' : (
46+
error ? error.message || 'error' : (
47+
!data ? 'No Data' : (
48+
<textarea cols="100" rows="30">{JSON.stringify(data, '', 2)}</textarea>
49+
)
50+
)
51+
)}
52+
</div>
53+
</div>
54+
);
55+
}

example/index.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7+
<title>react hooks example</title>
8+
</head>
9+
<body>
10+
<div id="app"></div>
11+
</body>
12+
</html>

example/index.js

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
4+
import App from './App';
5+
6+
ReactDOM.render(<App />, document.getElementById('app'));
7+
8+
if (module.hot) {
9+
module.hot.accept();
10+
}

package.json

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"name": "@use-hooks/axios",
3+
"version": "1.0.0",
4+
"description": "Custom React Hooks for Axios.js",
5+
"main": "dist/index.js",
6+
"files": [
7+
"dist"
8+
],
9+
"scripts": {
10+
"start": "webpack-dev-server --progress --color --config ./webpack.config.dev.js",
11+
"build": "webpack --config ./webpack.config.prod.js",
12+
"lint": "eslint src",
13+
"lint:fix": "eslint src --fix",
14+
"prepublishOnly": "npm run build"
15+
},
16+
"repository": {
17+
"type": "git",
18+
"url": "git+https://github.com/use-hooks/react-hooks-axios.git"
19+
},
20+
"keywords": [
21+
"reactjs",
22+
"react-hooks",
23+
"axios"
24+
],
25+
"author": "Cody Chan <[email protected]>",
26+
"license": "MIT",
27+
"bugs": {
28+
"url": "https://github.com/use-hooks/react-hooks-axios/issues"
29+
},
30+
"homepage": "https://github.com/use-hooks/react-hooks-axios#readme",
31+
"devDependencies": {
32+
"@babel/core": "^7.2.0",
33+
"@babel/preset-env": "^7.2.0",
34+
"@babel/preset-react": "^7.0.0",
35+
"babel-eslint": "^10.0.1",
36+
"babel-loader": "^8.0.4",
37+
"eslint": "^5.10.0",
38+
"eslint-plugin-react": "^7.11.1",
39+
"eslint-plugin-react-hooks": "^0.0.0",
40+
"html-webpack-plugin": "^3.2.0",
41+
"husky": "^1.2.0",
42+
"lint-staged": "^8.1.0",
43+
"webpack": "^4.27.1",
44+
"webpack-cli": "^3.1.2",
45+
"webpack-dev-server": "^3.1.10"
46+
},
47+
"husky": {
48+
"hooks": {
49+
"pre-commit": "lint-staged"
50+
}
51+
},
52+
"lint-staged": {
53+
"*.js": [
54+
"eslint --fix",
55+
"git add"
56+
]
57+
},
58+
"dependencies": {
59+
"axios": "^0.18.0",
60+
"react": "^16.7.0-alpha.2",
61+
"react-dom": "^16.7.0-alpha.2"
62+
}
63+
}

src/index.js

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { useState, useEffect } from 'react';
2+
import axios from 'axios';
3+
4+
export default ({
5+
url,
6+
method = 'get',
7+
// https://github.com/axios/axios#request-config
8+
options,
9+
// text / json
10+
trigger,
11+
filter = () => true,
12+
customHandler = () => {},
13+
} = {}) => {
14+
const [results, setResults] = useState({ response: null, error: null, loading: false });
15+
const [innerTrigger, setInnerTrigger] = useState(0);
16+
17+
let outerTrigger = trigger;
18+
try {
19+
outerTrigger = JSON.stringify(trigger);
20+
} catch (err) {
21+
//
22+
}
23+
24+
useEffect(() => {
25+
if (!url || !filter()) return;
26+
// ONLY trigger by query
27+
if (typeof outerTrigger === 'undefined' && !innerTrigger) return;
28+
customHandler(null, null);
29+
setResults({ response: null, error: null, loading: true });
30+
axios({
31+
url,
32+
method,
33+
...options,
34+
}).then((response) => {
35+
customHandler(null, response);
36+
setResults({ response, error: null, loading: false });
37+
}).catch((error) => {
38+
customHandler(error, null);
39+
setResults({ response: null, error, loading: false });
40+
});
41+
}, [innerTrigger, outerTrigger]);
42+
43+
return {
44+
...results,
45+
query: () => { setInnerTrigger(+new Date()); },
46+
};
47+
};

webpack.config.dev.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
const path = require('path');
2+
const webpack = require('webpack');
3+
const HtmlWebpackPlugin = require('html-webpack-plugin');
4+
5+
module.exports = {
6+
mode: 'development',
7+
entry: './example/index.js',
8+
9+
output: {
10+
path: path.join(__dirname, 'dist'),
11+
filename: 'index.js',
12+
},
13+
14+
devtool: 'inline-source-map',
15+
16+
devServer: {
17+
contentBase: [path.join(__dirname, 'dist')],
18+
hot: true,
19+
open: true,
20+
},
21+
22+
module: {
23+
rules: [
24+
{
25+
test: /\.js?$/,
26+
exclude: /node_modules/,
27+
use: ['babel-loader'],
28+
},
29+
],
30+
},
31+
32+
plugins: [
33+
new HtmlWebpackPlugin({
34+
template: 'example/index.html',
35+
}),
36+
new webpack.NamedModulesPlugin(),
37+
new webpack.HotModuleReplacementPlugin(),
38+
],
39+
40+
};

webpack.config.prod.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const path = require('path');
2+
3+
module.exports = {
4+
mode: 'production',
5+
entry: './src',
6+
7+
output: {
8+
path: path.join(__dirname, 'dist'),
9+
filename: 'index.js',
10+
libraryTarget: 'umd',
11+
},
12+
13+
externals: {
14+
react: 'react',
15+
},
16+
17+
module: {
18+
rules: [
19+
{
20+
test: /\.js?$/,
21+
exclude: /node_modules/,
22+
use: ['babel-loader'],
23+
},
24+
],
25+
},
26+
27+
};

0 commit comments

Comments
 (0)