# react-selfdefine-hook **Repository Path**: cai-lunduo/react-selfdefine-hook ## Basic Information - **Project Name**: react-selfdefine-hook - **Description**: react的自定义hook使用 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-05-30 - **Last Updated**: 2021-05-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### 自定义Hook(补充) 自定义hook可以让我们将组件逻辑提取到一个可重复利用的组件内。 这里会有两个案例讲解自定义hook的使用 **第一个简单的例子**: ```react import {useState, useEffect} from 'react' function Comp() { let [num, setNum] = useState(0) useEffect(() => { setTimeout(() => { setNum(++num) }, 2000) }, []) return (

Comp -- {num}

) } function App() { return (
); } export default App; ``` 如上所示,我们可以将`Comp`组件的 ```react let [num, setNum] = useState(0) useEffect(() => { setTimeout(() => { setNum(++num) }, 2000) }, []) ``` 给提取到一个单独的组件中,这时候便是一个自定义hook,使得我们调用的代码更简洁,且逻辑抽离到了一起。 我们将上述代码抽离到`./hooks/numHook.js`中。 ```react import {useState, useEffect} from 'react' export default function useNum() { let [num, setNum] = useState(0) useEffect(() => { setTimeout(() => { setNum(++num) }, 2000) }, []) return [num, setNum] } ``` 这时候我们在需要引用该hook的地方进行导入引用即可,例子将可以改写为: ```react import useNum from './hooks/numHook' function Comp() { let [num] = useNum() return (

Comp -- {num}

) } function App() { return (
); } export default App; ``` 这就是最简单的自定义hook。 ### 自定义请求数据hook 这里我们要做的自定义Hook是发起数据请求的hook 实现效果如下: ![image-20210530111434733](https://gitee.com/cai-lunduo/react-selfdefine-hook/raw/master/public/effects.jpg) 安装bootstrap: ```shell npm i -S bootstrap ``` **server端**: ```js const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors()) app.get('/list', (req, res) => { // 当前页和每页多少条 let {currentPage, perSize} = req.query perSize = parseInt(perSize, 10) // 数据 页数和条数对应得数据 let list = [] // 总数据条数 let total = 66 // 总页数 let pageCount = Math.ceil(total / perSize) // 起始索引 let offset = (currentPage - 1) * perSize if(currentPage >= pageCount) { perSize = total % perSize } for(let i = offset; i < offset + perSize; i++) { list.push({id: i+1, name: 'cai-'+(i+1)}) } res.json({ currentPage, perSize, total, pageCount, list }) }) app.listen(8080, () => { console.log('listening on 8080...') }) ``` 记得先启动服务端: ```node node server ``` 在`./hooks/useRequest.js`中: ```react import {useState, useEffect} from 'react' export default function useRequest() { /* 用户可更改的请求数据 */ let [options, setOptions] = useState({currentPage: 1, pageSize: 10}) let [data, setData] = useState({ total: 0, pageCount: 0, list: [] }) // 请求数据 function reqeust() { let {currentPage, pageSize} = options fetch(`http://localhost:8080/list?currentPage=${currentPage}&perSize=${pageSize}`) .then(res => res.json()) .then(res => setData({...res})) } useEffect(reqeust, [options]) return [data, options, setOptions] } ``` 这里的options state是单独抽离出来的,因为我们要返回给组件setOptions让他自定义请求参数(如:用户点击下一页时我们要重新改变请求参数的`currentPage`为当前页+1)。 ```js onClick={() => { setOptions({ ...options, currentPage: index + 1 }) }} ``` 组件一旦挂载我们就发起数据请求,然后将通过`setData`设置数据,并将`data`返回。可以看到最后返回的格式是[data, options, setOptions],意味着我们在组件内可以通过类似`useState`的方式获取自定义hook的值。 下面组件的取法: ```js let [data, options, setOptions] = useRequest() ``` 在`./pages/Tabel.js`中: ```react import {useState} from 'react' import useRequest from '../hooks/useRequest' export default function Table() { let [data, options, setOptions] = useRequest() let { list, pageCount } = data let [size, setSize] = useState(10) return ( <> {list.map((item) => { return ( ) })}
id name
{item.id} {item.name}
{/* 下拉框 */}
) } ```