diff --git a/.github/workflows/publish-example.yml b/.github/workflows/publish-example.yml deleted file mode 100644 index d5b8be2..0000000 --- a/.github/workflows/publish-example.yml +++ /dev/null @@ -1,46 +0,0 @@ -# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created -# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages - -name: Publish Example - -on: - pull_request: - branches: [ master ] - types: - - closed -jobs: - publish-npm: - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 16 - registry-url: https://registry.npmjs.org/ - - - name: Install 🔧 - run: npm i --legacy-peer-deps - - - name: Build Lib 🏗️ - run: npm run build:lib - - - name: Init Example - run: npm run init-example - - - name: Build example - run: npm run build:example - - - name: Deploy to GH Pages 🚀 - uses: peaceiris/actions-gh-pages@v3 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./example/build - - - name: Publish Npm - env: - NODE_AUTH_TOKEN: ${{secrets.KNE_PACKAGE_PUBLISH}} - run: cd example && npm publish --access=public - ## 请修改对应的packageName后取消以下命令的注释 - - name: Sync To Cnpm - run: npm i -g cnpm && cnpm sync @kne-components/react-fetch diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f79c737..8d918b3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,34 +1,14 @@ -# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created -# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages - -name: Publish Package - +name: Publish Npm Package on: pull_request: branches: [master] types: - closed jobs: - publish-npm: + libs-npm: if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: 16 - registry-url: https://registry.npmjs.org/ - - - name: Install 🔧 - run: npm install --legacy-peer-deps - - - name: Build 🏗️ - run: npm run build:lib - - - name: Publish Npm - env: - NODE_AUTH_TOKEN: ${{secrets.KNE_PACKAGE_PUBLISH}} - run: npm publish --access=public - ## 请修改对应的packageName后取消以下命令的注释 - - name: Sync To Cnpm - run: npm i -g cnpm && cnpm sync @kne/react-fetch + uses: kne-union/actions/.github/workflows/publish-libs-workflow.yml@master + secrets: inherit + with: + package_name: '@kne/react-fetch' + example_package_name: '@kne-components/react-fetch' diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..874e5c1 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +npm run build:md diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b3d9fb9 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,16 @@ +{ + "arrowParens": "avoid", + "bracketSpacing": true, + "htmlWhitespaceSensitivity": "css", + "insertPragma": false, + "jsxBracketSameLine": true, + "jsxSingleQuote": false, + "printWidth": 240, + "proseWrap": "preserve", + "requirePragma": false, + "semi": true, + "singleQuote": true, + "trailingComma": "none", + "useTabs": false, + "tabWidth": 2 +} diff --git a/README.md b/README.md index 10a2c42..e5f6cac 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,16 @@ preset({ }); return; } + if (config.url === '/data3') { + console.log('data1 request'); + resolve({ + data: [ + {title: '数据一'}, + {title: '数据二'} + ] + }); + return; + } if (config.url === '/data2') { resolve({ data: { @@ -377,7 +387,7 @@ render(); ```jsx const {createWithFetch} = ReactFetch; -const {default: List} = AntdList; +const {List} = antd; const Remote = createWithFetch({ url: '/data1', @@ -445,6 +455,52 @@ render(); ``` +- 忽略请求成功状态 +- 发送一个成功请求,内部组件拿到数据并展示数据 +- ReactFetch(@kne/react-fetch),antd(antd) + +```jsx +const {createWithFetch} = ReactFetch; +const {List} = antd; + +const Remote = createWithFetch({ + url: '/data3', ignoreSuccessState: true +})(({data}) => { + return + {data.map((item, index) => { + return {item.title} + })} + ; +}); + +render(); + +``` + +- url params +- 发送一个成功请求,内部组件拿到数据并展示数据 +- ReactFetch(@kne/react-fetch),antd(antd) + +```jsx +const {createWithFetch} = ReactFetch; +const {List} = antd; + +const Remote = createWithFetch({ + url: '/data{id}', urlParams: { + id: 1 + } +})(({data}) => { + return + {data.map((item, index) => { + return {item.title} + })} + ; +}); + +render(); + +``` + ### API @@ -484,18 +540,20 @@ React Hooks options: -| 属性名 | 说明 | 类型 | 默认值 | -|-------------------|--------------------------------------------------------------------------|----------|-------| -| url | 需要请求接口的url | string | - | -| data | POST请求的data | object | - | -| params | GET请求的query | object | - | -| options | 请求的其他参数,如method,headers等,详细请参考[axios](https://github.com/axios/axios) | object | - | -| auto | 是否自动发送请求,如果为false需要手动调用refresh方法才会发送请求,并且url,data,options发生变化后不会自动发送新的请求 | boolean | true | -| debug | 是否开启调试,开启以后可以在控制台打印整个组件的plugin执行堆栈,可以帮助排查问题 | boolean | false | -| onRequestStart | 请求开始时回调方法 | function | - | -| onRequestError | 请求发生错误时回调方法 | function | - | -| onRequestSuccess | 请求成功时回调方法 | function | - | -| onRequestComplete | 请求完成时(包括成功和失败)的回调方法 | function | - | +| 属性名 | 说明 | 类型 | 默认值 | +|--------------------|----------------------------------------------------------------------------|----------|-------| +| url | 需要请求接口的url | string | - | +| data | POST请求的data | object | - | +| params | GET请求的query | object | - | +| options | 请求的其他参数,如method,headers等,详细请参考[axios](https://github.com/axios/axios) | object | - | +| urlParams | url模板参数,当url为 /example/{id}且传入urlParams为{id:123},真正发出请求的url为: /example/123 | object | - | +| ignoreSuccessState | 当且仅当该参数为true时在output阶段不再判断返回数据的code===200为请求成功,且返回data不再取results而是返回data本身 | boolean | - | +| auto | 是否自动发送请求,如果为false需要手动调用refresh方法才会发送请求,并且url,data,options发生变化后不会自动发送新的请求 | boolean | true | +| debug | 是否开启调试,开启以后可以在控制台打印整个组件的plugin执行堆栈,可以帮助排查问题 | boolean | false | +| onRequestStart | 请求开始时回调方法 | function | - | +| onRequestError | 请求发生错误时回调方法 | function | - | +| onRequestSuccess | 请求成功时回调方法 | function | - | +| onRequestComplete | 请求完成时(包括成功和失败)的回调方法 | function | - | 返回值 @@ -533,3 +591,13 @@ Fetch options | ttl | 缓存失效时间,为0的时候不失效,单位为毫秒 | number | 0 | | isLocal | 缓存是否存储到localStorge | bool | false | +### request + +导出一个行为,参数和Fetch一致的方法,调用后发送一个ajax请求 + +使用方法 + +```js +request(props) +``` + diff --git a/doc/api.md b/doc/api.md index e0bd8d8..e2b7b6d 100644 --- a/doc/api.md +++ b/doc/api.md @@ -34,18 +34,20 @@ React Hooks options: -| 属性名 | 说明 | 类型 | 默认值 | -|-------------------|--------------------------------------------------------------------------|----------|-------| -| url | 需要请求接口的url | string | - | -| data | POST请求的data | object | - | -| params | GET请求的query | object | - | -| options | 请求的其他参数,如method,headers等,详细请参考[axios](https://github.com/axios/axios) | object | - | -| auto | 是否自动发送请求,如果为false需要手动调用refresh方法才会发送请求,并且url,data,options发生变化后不会自动发送新的请求 | boolean | true | -| debug | 是否开启调试,开启以后可以在控制台打印整个组件的plugin执行堆栈,可以帮助排查问题 | boolean | false | -| onRequestStart | 请求开始时回调方法 | function | - | -| onRequestError | 请求发生错误时回调方法 | function | - | -| onRequestSuccess | 请求成功时回调方法 | function | - | -| onRequestComplete | 请求完成时(包括成功和失败)的回调方法 | function | - | +| 属性名 | 说明 | 类型 | 默认值 | +|--------------------|----------------------------------------------------------------------------|----------|-------| +| url | 需要请求接口的url | string | - | +| data | POST请求的data | object | - | +| params | GET请求的query | object | - | +| options | 请求的其他参数,如method,headers等,详细请参考[axios](https://github.com/axios/axios) | object | - | +| urlParams | url模板参数,当url为 /example/{id}且传入urlParams为{id:123},真正发出请求的url为: /example/123 | object | - | +| ignoreSuccessState | 当且仅当该参数为true时在output阶段不再判断返回数据的code===200为请求成功,且返回data不再取results而是返回data本身 | boolean | - | +| auto | 是否自动发送请求,如果为false需要手动调用refresh方法才会发送请求,并且url,data,options发生变化后不会自动发送新的请求 | boolean | true | +| debug | 是否开启调试,开启以后可以在控制台打印整个组件的plugin执行堆栈,可以帮助排查问题 | boolean | false | +| onRequestStart | 请求开始时回调方法 | function | - | +| onRequestError | 请求发生错误时回调方法 | function | - | +| onRequestSuccess | 请求成功时回调方法 | function | - | +| onRequestComplete | 请求完成时(包括成功和失败)的回调方法 | function | - | 返回值 @@ -82,3 +84,13 @@ Fetch options | cache | 为true或者为字符串的时候为开启缓存,如果请求参数完全一致则命中缓存。如果cache为字符串,只有cahce一致的组件之间会命中缓存 | boolean|string | - | | ttl | 缓存失效时间,为0的时候不失效,单位为毫秒 | number | 0 | | isLocal | 缓存是否存储到localStorge | bool | false | + +### request + +导出一个行为,参数和Fetch一致的方法,调用后发送一个ajax请求 + +使用方法 + +```js +request(props) +``` diff --git a/doc/base.code b/doc/base.js similarity index 100% rename from doc/base.code rename to doc/base.js diff --git a/doc/cache.code b/doc/cache.js similarity index 100% rename from doc/cache.code rename to doc/cache.js diff --git a/doc/empty.code b/doc/empty.js similarity index 100% rename from doc/empty.code rename to doc/empty.js diff --git a/doc/error.code b/doc/error.js similarity index 100% rename from doc/error.code rename to doc/error.js diff --git a/doc/example.json b/doc/example.json index 302d5bd..583b155 100644 --- a/doc/example.json +++ b/doc/example.json @@ -4,7 +4,7 @@ { "title": "preset设置", "description": "注意:react-fetch 内部处理请求的时候只通过 code,msg,results来作为内部逻辑,code为200判定为请求成功,不为200时判定为错误,msg会传入到error组件,拿到results后,会将results作为业务组件的data属性\n如果后端的返回不满足上诉格式,需要在preset的transformResponse方法做转换适配\najax为一个axios实例,每个实例的拦截器可能不同,默认会在内部自动创建一个axios实例,但是没有任何拦截器,如果想给其添加拦截器,可以自行创建axios实例通过preset设置\npreset 可以单独放一个文件里,在入口文件顶部引入。\npreset全局设置一次即可。", - "code": "./mock-data.code", + "code": "./mock-data.js", "scope": [ { "name": "ReactFetch", @@ -23,7 +23,7 @@ { "title": "请求成功", "description": "发送一个成功请求,内部组件拿到数据并展示数据", - "code": "./base.code", + "code": "./base.js", "scope": [ { "name": "ReactFetch", @@ -38,7 +38,7 @@ { "title": "使用Fetch组件发送请求", "description": "使用Fetch组件发送一个成功请求,内部组件拿到数据并展示数据", - "code": "./fetch.code", + "code": "./fetch.js", "scope": [ { "name": "ReactFetch", @@ -53,7 +53,7 @@ { "title": "请求失败", "description": "发送一个失败请求,内部组件不渲染,直接展示错误信息", - "code": "./error.code", + "code": "./error.js", "scope": [ { "name": "ReactFetch", @@ -64,7 +64,7 @@ { "title": "分页数据请求", "description": "分页加载数据", - "code": "./page.code", + "code": "./page.js", "scope": [ { "name": "ReactFetch", @@ -83,7 +83,7 @@ { "title": "下拉加载更多", "description": "下拉加载更多数据", - "code": "./load-more.code", + "code": "./load-more.js", "scope": [ { "name": "ReactFetch", @@ -102,7 +102,7 @@ { "title": "空数据", "description": "用isEmpty判断数据是不是空状态", - "code": "./empty.code", + "code": "./empty.js", "scope": [ { "name": "ReactFetch", @@ -117,7 +117,7 @@ { "title": "用loader加载数据", "description": "展示了用loader来加载数据的例子", - "code": "./loader.code", + "code": "./loader.js", "scope": [ { "name": "ReactFetch", @@ -128,7 +128,7 @@ { "title": "transform", "description": "展示transformResponse的调用", - "code": "./transform.code", + "code": "./transform.js", "scope": [ { "name": "ReactFetch", @@ -143,7 +143,37 @@ { "title": "缓存操作", "description": "展示缓存操作", - "code": "./cache.code", + "code": "./cache.js", + "scope": [ + { + "name": "ReactFetch", + "packageName": "@kne/react-fetch" + }, + { + "name": "antd", + "packageName": "antd" + } + ] + }, + { + "title": "忽略请求成功状态", + "description": "发送一个成功请求,内部组件拿到数据并展示数据", + "code": "./ignore-success-state.js", + "scope": [ + { + "name": "ReactFetch", + "packageName": "@kne/react-fetch" + }, + { + "name": "antd", + "packageName": "antd" + } + ] + }, + { + "title": "url params", + "description": "发送一个成功请求,内部组件拿到数据并展示数据", + "code": "./url-params.js", "scope": [ { "name": "ReactFetch", diff --git a/doc/fetch.code b/doc/fetch.js similarity index 100% rename from doc/fetch.code rename to doc/fetch.js diff --git a/doc/ignore-success-state.js b/doc/ignore-success-state.js new file mode 100644 index 0000000..a89a368 --- /dev/null +++ b/doc/ignore-success-state.js @@ -0,0 +1,14 @@ +const {createWithFetch} = ReactFetch; +const {List} = antd; + +const Remote = createWithFetch({ + url: '/data3', ignoreSuccessState: true +})(({data}) => { + return + {data.map((item, index) => { + return {item.title} + })} + ; +}); + +render(); diff --git a/doc/load-more.code b/doc/load-more.js similarity index 100% rename from doc/load-more.code rename to doc/load-more.js diff --git a/doc/loader.code b/doc/loader.js similarity index 100% rename from doc/loader.code rename to doc/loader.js diff --git a/doc/mock-data.code b/doc/mock-data.js similarity index 86% rename from doc/mock-data.code rename to doc/mock-data.js index 496ccec..e6414db 100644 --- a/doc/mock-data.code +++ b/doc/mock-data.js @@ -20,6 +20,16 @@ preset({ }); return; } + if (config.url === '/data3') { + console.log('data1 request'); + resolve({ + data: [ + {title: '数据一'}, + {title: '数据二'} + ] + }); + return; + } if (config.url === '/data2') { resolve({ data: { diff --git a/doc/page.code b/doc/page.js similarity index 100% rename from doc/page.code rename to doc/page.js diff --git a/doc/transform.code b/doc/transform.js similarity index 94% rename from doc/transform.code rename to doc/transform.js index d97cd07..753330d 100644 --- a/doc/transform.code +++ b/doc/transform.js @@ -1,5 +1,5 @@ const {createWithFetch} = ReactFetch; -const {default: List} = AntdList; +const {List} = antd; const Remote = createWithFetch({ url: '/data1', diff --git a/doc/url-params.js b/doc/url-params.js new file mode 100644 index 0000000..131669d --- /dev/null +++ b/doc/url-params.js @@ -0,0 +1,16 @@ +const {createWithFetch} = ReactFetch; +const {List} = antd; + +const Remote = createWithFetch({ + url: '/data{id}', urlParams: { + id: 1 + } +})(({data}) => { + return + {data.map((item, index) => { + return {item.title} + })} + ; +}); + +render(); diff --git a/package.json b/package.json index af5d76d..d5ccefa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kne/react-fetch", - "version": "1.4.3", + "version": "1.5.0", "description": "用于获取数据的react组件", "main": "dist/index.js", "module": "dist/index.modern.js", @@ -9,20 +9,22 @@ "esmodules": true }, "scripts": { + "init": "husky && npm run init-example", + "start": "run-p start:lib start:md start:example", + "build": "run-s build:lib build:md build:example", "init-example": "modules-dev-libs-init", - "start": "run-p start:lib start:example", - "build": "run-s build:lib build:example", - "build:lib": "microbundle --no-compress --format modern,cjs --jsx React.createElement", - "start:lib": "microbundle watch --no-compress --format modern,cjs --jsx React.createElement", - "test": "run-s test:unit test:lint test:build", + "build:md": "npx @kne/md-doc", + "start:md": "npx @kne/md-doc --watch", + "build:lib": "microbundle --no-compress --format modern,cjs --jsx React.createElement --jsxFragment React.Fragment", + "start:lib": "microbundle watch --no-compress --format modern,cjs --jsx React.createElement --jsxFragment React.Fragment", + "build:example": "cd example && npm run build", + "start:example": "cd example && npm run start", "test:build": "run-s build", "test:lint": "eslint .", "test:unit": "cross-env CI=1 react-scripts test --env=jsdom", "test:watch": "react-scripts test --env=jsdom", - "build:example": "cd example && npm run build", - "start:example": "cd example && npm run start", - "lint-staged": "lint-staged", - "prepare": "husky install" + "prettier": "prettier --config .prettierrc --write '{src/**/*,index,prompts}.{js,jsx,ts,tsx,json,css,scss}'", + "lint-staged": "npx lint-staged" }, "repository": { "type": "git", @@ -54,19 +56,14 @@ "react-dom": ">=16.x" }, "devDependencies": { - "@craco/craco": "^7.1.0", - "@kne/md-doc": "^0.1.2", - "@kne/microbundle": "^0.15.4", - "@kne/modules-dev": "^2.0.5", - "axios": "^0.26.1", + "@kne/microbundle": "^0.15.5", + "@kne/modules-dev": "^2.0.14", "cross-env": "^7.0.3", - "gh-pages": "^3.2.3", - "husky": "^7.0.4", + "husky": "^9.0.11", "npm-run-all": "^4.1.5", - "prettier": "^2.5.1", + "prettier": "^3.2.5", "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-scripts": "^5.0.1" + "react-dom": "^18.2.0" }, "dependencies": { "lodash": "^4.17.21", diff --git a/src/Fetch.js b/src/Fetch.js index 9a6d972..4fbac79 100644 --- a/src/Fetch.js +++ b/src/Fetch.js @@ -8,7 +8,7 @@ const Fetch = forwardRef(({component, render, loading, isEmpty, empty, error: er const { isLoading, isComplete, data, requestParams, error, send, refresh, reload, loadMore, setData } = useFetch(props); - const fetchPropsList = ['url', 'params', 'method', 'data', 'cache', 'ttl', 'isLocal', 'auto', 'loader', 'options', 'updateType', 'onRequestError', 'onRequestSuccess', 'onRequestComplete', 'onRequestStart', 'debug', 'ajax', 'transformData', 'transformResponse']; + const fetchPropsList = ['url', 'params', 'urlParams', 'method', 'data', 'cache', 'ttl', 'isLocal', 'auto', 'loader', 'options', 'updateType', 'onRequestError', 'onRequestSuccess', 'onRequestComplete', 'onRequestStart', 'debug', 'ajax', 'transformData', 'transformResponse']; const otherProps = omit(props, fetchPropsList); const fetchProps = pick(props, fetchPropsList); useImperativeHandle(ref, () => { diff --git a/src/getRequestToken.js b/src/getRequestToken.js new file mode 100644 index 0000000..95ffdf5 --- /dev/null +++ b/src/getRequestToken.js @@ -0,0 +1,8 @@ +import pick from "lodash/pick"; +import objectHash from "object-hash"; + +const getRequestToken = (props) => objectHash(pick(props, ['url', 'params', 'method', 'data', 'urlParams', 'options']), { + algorithm: 'md5', encoding: 'base64' +}); + +export default getRequestToken; diff --git a/src/index.js b/src/index.js index 095a531..adac352 100644 --- a/src/index.js +++ b/src/index.js @@ -3,3 +3,4 @@ export {default as Cache} from './Cache'; export {default as useFetch} from './useFetch'; export {default as withFetch, createWithFetch} from './withFetch'; export {default as preset, getCache} from './preset'; +export {default as request} from './request'; diff --git a/src/plugins/output-data.js b/src/plugins/output-data.js index 02e1d26..da786b2 100644 --- a/src/plugins/output-data.js +++ b/src/plugins/output-data.js @@ -1,16 +1,17 @@ export default { id: 'output-data', plugin: (props, context) => { - const {onRequestSuccess, transformData} = context.componentContext.getProps(); + const {options, onRequestSuccess, ignoreSuccessState, transformData} = context.componentContext.getProps(); if (Object.keys(context.errorStack).length > 0) { return; } + const responseData = context.output.data; - if (responseData.code !== 200) { + if (ignoreSuccessState !== true && responseData.code !== 200) { const error = new Error(responseData.msg); error.responseData = responseData; throw error; } - const output = ((output) => typeof transformData === 'function' ? transformData(output, context.outputStack['params']) : output)(responseData.results || {}); + const output = ((output) => typeof transformData === 'function' ? transformData(output, context.outputStack['params']) : output)((ignoreSuccessState !== true ? responseData.results : responseData) || {}); onRequestSuccess && onRequestSuccess(output); return output; }, dependencies: ['request'] diff --git a/src/plugins/params.js b/src/plugins/params.js index cb43518..5e2d056 100644 --- a/src/plugins/params.js +++ b/src/plugins/params.js @@ -2,16 +2,20 @@ import merge from "lodash/merge"; import pick from 'lodash/pick'; export default { - id: 'params', - plugin: ({options, url, method, params, data}, context) => { - const {options: componentOptions, ...componentProps} = context.componentContext.getProps(); - const output = merge({}, componentOptions, pick(componentProps, ['url', 'method', 'params', 'data']), options, { - url, - method, - params, - data + id: 'params', plugin: ({options, url, method, params, data}, context) => { + const {options: componentOptions, urlParams, ...componentProps} = context.componentContext.getProps(); + const targetParams = merge({}, componentOptions, pick(componentProps, ['url', 'method', 'params', 'data']), options, { + url, method, params, data, urlParams }); - context.componentContext.setRequestParams(output); + + const output = Object.assign({}, targetParams); + if (typeof urlParams === 'object' && Object.keys(urlParams).length > 0 && typeof output.url === 'string') { + output.url = output.url.replace(/{([\s\S]+?)}/g, (match, name) => { + return urlParams.hasOwnProperty(name) ? urlParams[name] : match; + }); + } + + context.componentContext.setRequestParams(targetParams); return output; } }; diff --git a/src/plugins/transform-response.js b/src/plugins/transform-response.js index 01aba82..4ab302d 100644 --- a/src/plugins/transform-response.js +++ b/src/plugins/transform-response.js @@ -2,11 +2,14 @@ import {globalParams} from "../preset"; export default { id: 'transform-response', plugin: (props, context) => { - const {transformResponse} = context.componentContext.getProps(); + const {transformResponse, ignoreSuccessState, options} = context.componentContext.getProps(); const response = context.outputStack['request']; if (!response) { return; } + if (ignoreSuccessState === true) { + return response; + } return (transformResponse || globalParams.transformResponse)(Object.assign({}, response)); }, dependencies: ['request'] }; diff --git a/src/request.js b/src/request.js new file mode 100644 index 0000000..f0afa90 --- /dev/null +++ b/src/request.js @@ -0,0 +1,23 @@ +import {createRunner} from "./plugins"; +import objectHash from "object-hash"; +import pick from "lodash/pick"; + +const request = (props) => { + const { + onRequestParamsChange, onRequestDataChange, onError, onIsCompleteChange, onIsLoadingChange, ...requestProps + } = Object.assign({}, props, {options: Object.assign({}, {ignoreSuccessState: true}, props?.options)}); + return createRunner({ + getProps: () => requestProps, + getRequestToken: () => objectHash(pick(requestProps, ['url', 'params', 'method', 'data', 'options']), { + algorithm: 'md5', encoding: 'base64' + }), + requestParams: {}, + setRequestParams: (...args) => onRequestParamsChange && onRequestParamsChange(...args), + setFetchData: (...args) => onRequestDataChange && onRequestDataChange(...args), + setError: (...args) => onError && onError(...args), + setIsComplete: (...args) => onIsCompleteChange && onIsCompleteChange(...args), + setIsLoading: (...args) => onIsLoadingChange && onIsLoadingChange(...args) + })(); +}; + +export default request; diff --git a/src/useFetch.js b/src/useFetch.js index 5cfd218..1d02675 100644 --- a/src/useFetch.js +++ b/src/useFetch.js @@ -1,12 +1,10 @@ import {useRef, useEffect, useState, useMemo} from 'react'; -import objectHash from "object-hash"; import {createRunner} from './plugins'; -import pick from 'lodash/pick'; +import getRequestToken from './getRequestToken'; const useFetch = (fetcherOptions) => { const props = Object.assign({ - auto: true, - updateType: 'reload' + auto: true, updateType: 'reload' }, fetcherOptions); const propsRef = useRef(props); @@ -25,10 +23,7 @@ const useFetch = (fetcherOptions) => { isLoading, isComplete, fetchData, error, requestParams }; - const requestToken = objectHash(pick(props, ['url', 'params', 'method', 'data', 'options']), { - algorithm: 'md5', - encoding: 'base64' - }); + const requestToken = getRequestToken(props); const requestTokenRef = useRef(requestToken); requestTokenRef.current = requestToken; @@ -76,8 +71,16 @@ const useFetch = (fetcherOptions) => { }, [requestToken]); return { - isLoading, isComplete, data: fetchData, error, - send, refresh, reload, loadMore, setData: setFetchData, requestParams + isLoading, + isComplete, + data: fetchData, + error, + send, + refresh, + reload, + loadMore, + setData: setFetchData, + requestParams }; };