此文章主要把近段时间使用react hooks开发遇到的一些问题和解决方法记录一下
一.使用样式的方法
方法1.当前页面定义样式
const btnStyle = {
width:'100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
<Button style={btnStyle}></Button>
方法2.引入样式
import '../style.less'
<Button className='btnStyle'></Button>
方法3.行内样式
<Button style={{width: '100%'}}></Button>
二.组件传参和方法调用
// 伪代码
// 父组件
export default function FatherPage() {
const [age, setAge] = useState<number>(12)
const handleReload = (data) => {
console.log(data) // 子组件传递过来的数据
}
return (
<div>
<ChildPage age={age} onResult={() => handleReload()}></ChildPage>
</div>
)
}
// 子组件
const ChildPage = (props) => {
console.log(props) // 这里可以获取到父组件传递过来的数据和方法
const handleClick = () => {
// 触发父组件的onResult方法,并且可以传参过去
props.onResult({
name: '张三',
age: 20
})
}
return (
<div>
我是子组件 { props.age }
<Button onClick={() => handleClick()}>按钮<Button>
</div>
)
}
export default ChildPage
三.改变数组和对象属性注意事项
直接更改数组或对象属性是无效的,因为其引用地址不会变,react不会重新加载
正确更改方式是复制引用,然后整个替换
// 伪代码
const [nodeObj, setNodeObj] = useState<any>({
age: 20,
name: '李四'
})
// 更新对象 使用扩展运算符创建一个全新的引用(副本),并设置一个新值
setNodeObj({...nodeObj, age: 10})
// 更新数组
const [array, setArray] = useState([
{'id': 0, text: '0'},
{'id': 1, text: '1'},
{'id': 2, text: '2'}
])
const copy = [...array]
// or => const copy = Array.from(array)
copy[2].text = '3'
setArray(copy)
四.hooks的钩子函数
// useState 返回一个 state,以及更新 state 的函数
const [age, setAge] = useState<number>(10)
// useEffect 可以监听数据的改变然后执行某些操作
useEffect(() => {
console.log(1111)
}, [nodeObj.id])
// useMount 进来时初始化数据
useMount(() => {
initData()
})
// useContext 跨层级传参
const itemObj = [
light:{
color: '#fff',
background: '#1890ff'
},
dark: {
color: '#fff',
background: '#0c0c0c'
}
]
const objContext = React.createContext(itemObj.dark) // 可以设置默认值
// 祖先组件
function App() {
return (
<ObjContext.Provider value={itemObj.light}>
<FatherPage />
</ObjContext.Provider>
);
}
// 父组件
function FatherPage(props) {
return (
<div>
<ChildPage />
</div>
)
}
// 子组件
function ChildPage(props) {
const theme = useContext(objContext) // 这里获取祖先组件传递的数据
return (
<button style={{ background: theme.background, color: theme.color }}>
useContext
</button>
);
}
以上几个是较为常用的钩子函数,还有useReducer,useCallback,useMemo,useRef,useImperativeHandle,useLayoutEffect,useDebugValue等有时间我会再写,或者各位感兴趣可以自己去了解
五.jsx里面的循环和判断
// 伪代码 (或者使用三目运算符,也可以在函数外部判断)
const dateList = [
{
value: 'permanent',
label: '永久'
},
{
value: 'year',
label: '一年'
},
{
value: 'month',
label: '一月'
},
{
value: 'week',
label: '一周'
},
{
value: 'day',
label: '一天'
}
]
{
{ type === 'custom' && (
<Select style={{ width: '300px' }} value="week" >
{ dateList.map(item => {
return (
<Select.Option value={item.value} key={item.value}>
{item.label}
</Select.Option>
)
}) }
</Select>
)
}
六. 父组件通过ref获取子组件的值或者方法
//父组件
import React, {useState, useEffect, useImperativeHandle, forwardRef} from 'react'
export default function Father() {
const childRef:any = useRef()
const handleClick = () => {
console.log(childRef.current.formValues) //获取子组件的值
childRef.current.cleanForm() // 调用子组件的方法
}
return (
<Button onClick={handleClick}></Button>
<Child ref="childRef" />
)
}
//子组件
const Child = (props: modalProps, ref: any) => {
const [checked, setChecked] = useState<boolean>(true)
useImperativeHandle(ref, () => ({
formValues: {
checked
},
cleanForm: () => {
setChecked(true)
}
}))
const onChange = (checked: boolean) => {
setChecked(checked)
}
return (
<div>
<Switch defaultChecked onChange={onChange} checked={checked} />
</div>
)
}
export default forwardRef(Child)
七. 封装组件
// 封装一个带form的modal
import React, {useState, useEffect, useImperativeHandle, forwardRef} from 'react'
import { Form, Modal, Input } from 'antd'
interface modalProps {
width? : string | number, // 宽度
title?: string, // 标题
visible : boolean, // 是否隐藏
okText?: string, // 确定文字
cancelText?: string, // 取消按钮文字
handleCancel?: () => void // 取消方法
handleOk?: () => void // 确定方法
}
const ModalForm = (props: modalProps, ref: any) => {
const { title, width='600px', visible, handleCancel, handleOk, okText='确定', cancelText= '取消'} = props
const [form] = Form.useForm()
useEffect(() => {
form.resetFields()
},[visible])
useImperativeHandle(ref, () => ({
getForm: () => form
}))
const layout = {
labelCol: { style: {
width: '120px'
}}
};
return (
<>
<Modal
width={width}
title={title}
onCancel={handleCancel}
visible={visible}
onOk={handleOk}
okText={okText}
cancelText={cancelText}
>
<Form {...layout} form={form} >
<Form.Item name="username" label="用户名" rules={[{ required: true, message: '请输入用户名' }]}>
<Input placeholder="用户名"/>
</Form.Item>
<Form.Item name="pwd" label="密码" rules={[{ required: true, message: '请输入密码' }]}>
<Input type="password" placeholder="密码"/>
</Form.Item>
</Form>
</Modal>
</>
)
}
export default forwardRef(ModalForm)
// 使用ModalForm组件
import ModalForm from './ModalForm'
const handleOk = () => {
console.log(refModal.current.getForm()) // 这里可以获取useForm的所有方法
}
export default function UseModal() {
const [visible, setVisible] = useState<boolean>(false)
const refModal:any = useRef()
return (
<>
<ModalForm ref={refModal} visible={visible} title="表单弹框" handleCancel={() => setVisible(false)} handleOk={handleOk} />
</>
)
}
有问题的地方欢迎指正