使用React Hook新特性遇到的一些问题
一、参数变化触发数据更新
使用场景:获取Table数据等
当Table数据的页码和筛选项变化的时候,想触发获取数据的方法运行
import React, { useState, useEffect } from 'react'export default () => {const [page, setPage] = useState(1)const [dataSource, setDataSource] = useState([])funtion loadData( ) {getdata({page,pageSize}).then(res => setDataSource(res.data))}// useEffect方法为函数组件渲染的时候会默认触发一次,当page参数变化的时候,loadData方法也会触发一次// useEffect的第二个参数为一个数组,可以添加多个数组对象,如[page, search]useEffect(loadData, [page])}
二、销毁函数组件的时候,怎么设置回调函数
使用场景:设置了定时器等方法的时候,组件销毁的时候清理定时器释放内存
import React, { useState, useEffect } from 'react'export default () => {const [count, setCount] = useState(0)const timer = setInterval(() => {setCount(count + 1)}, 1000)// useEffect方法的第一个参数是一个函数,函数可以return一个方法,这个方法就是在组件销毁的时候会被调用useEffect(() => {return () => {clearInterval(timer)}}, [])}
三、如何拿到函数组件内的ref三、如何拿到函数组件内的ref
使用场景:子组件内使用了一些输入框Input等组件的时候,想在父组件内获取子组件的Input的ref方法
import React, { useState, useEffect } from 'react'import { Input } from 'antd'export const Child = React.forwardRef((props, ref) => {// 当外部传入ref时,可以通过forwardRef的第二个参数获取到ref属性的值// ref如果有值,就赋值把控制权给父组件;若为空,则可以在子组件内部控制Inputconst inputRef = ref || React.createRef()return <><Input ref={inputRef} /></>})export default class Father extends React.Component {constuctor (props) {super(props)this.inputRef = React.createRef()}componentDidMount () {// 1妙后让Child组件的Input标签聚焦setTimeout(() => {this.textRef.current.focus()}, 1000)}render () {// 通过ref传递inputRef参数,从而获取到Input的控制权return <><Child ref={this.inputRef} /></>}}
四、用函数组件制作Table列表,筛选条件让useState十分臃肿
使用场景:Table的筛选项有page、search、dateTime、order、type等等
如果给每个筛选项加一个useState来控制的话,不得不说代码会比较臃肿,难以维护且不优雅(装起来了就),下面就来解决一下这个痛点
// utils.jsimport { useState } from 'react'export default (initial, setPage) => {const [state, setState] = useState(initial)return [state, function (newState) {// 每次筛选条件变化的时候,就重新设置到第一页,setPage && setPage(1)// 新的覆盖参数覆盖掉老的参数setState({ ...state, ...newState })}]}// index.jsimport React, { useState, useEffect } from 'react'import { Table } from 'antd'import useMergeFilter from './utils'export default () => {const [dataSource, setDataSource] = useState([])const [page, setPage] = useState(1)const [total, setTotal] = useState(0)const [filter, setFilter] = useMergeFilter({ keyword: undefined, status: '' }, setPage)function loadData () {// 将参数展开传入getdata({ page, pageSize, ...filter }).then(res => setDataSource(res.data))}// 每次filter和page变化都会触发loadDate函数运行useEffect(loadData, [filter, page])return <><div className='filter'>// 只需在回调函数里执行setFilter并传入需要的参数,就能触发列表更新<Input.Search placeholder='搜索' onSearch={value => setFilter({ keyword: value })} /><Select defaultValue='' onChange={value => setFilter({ status: value })}><Select.Option value='A'>A</Select.Option><Select.Option value='B'>B</Select.Option></Select></div><Tablecolumns={columns()}dataSource={dataSource}/></>}
五、新特性函数组件结合antd的表单form组件
使用场景:函数组件内使用表单,获取form属性
这个使用场景就比较多了,正常的类组件我们都会,antd的官方也有介绍;但用函数组件写有的同学就会有点懵,form去哪里取
import React, { useState, useEffect } from 'react'import { Form, Button } from 'antd'// 抛出函数组件的时候,通过Form.create()方法生成的新的组件,可以通过({ form })的形式拿到整个表单的form对象// 下面就可以随心所欲的操作form内的表单数据了const Demo = ({ form }) => {const handleSubmit = (e) => {e.preventDefault()form.validateFields((err, values) => {console.log('err', err)console.log('values', values)})}<Form onSubmit={handleSubmit}><div><FormItem label='用户ID'>{getFieldDecorator('id', {initialValue: '',})(<Input placeholder='输入用户名id' />)}</FormItem><Form.Item><Button type='primary' htmlType='submit'>提交</Button></Form.Item></div></Form>}const WrappedRegistrationForm = Form.create()(Demo)export default WrappedRegistrationForm
