「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」
useRef
返回一个可变的
ref对象,其.current属性,被初始化为传入参数。返回的ref对象在整个生命周期内保持不变。
const valueRef = useRef(initialValue)
对比createRef :实现点击按钮,input被选中
import { useRef } from 'react';
export default {
const inputRef = useRef(null)
const handleFocusInput= () => {
inputElement.current.focus();
}
return (
<>
<input ref={inputRef} type="text"/>
<button onClick={handleFocusInput}>Focus input</button>
</>
)
}
import { createRef } from 'react';
export default (props: any) => {
const inputElement = createRef<HTMLDivElement>();
const handleFocusInput = () => {
inputElement.current.focus();
}
return (
<>
<input ref={inputElement} type="text"/>
<button onClick={handleFocusInput}>Focus input</button>
</>
);
}
createRef每次渲染都会返回一个新的引用,useRef每次都会返回相同的引用。
这一篇文章写的很好: # 什么是 useRef , useRef 与 createRef 区别, 以及在什么情况下使用 useRef, 以及这一篇讲了关于 useRef的“跨渲染周期”保存数据。
【实操】
import { useState, useRef } from 'react';
import { Form, Button, Modal } from 'antd';
import type { FormInstance } from 'antd/lib/form';
export default {
const inputRef = useRef<Input | null>(null);
const formRef = React.createRef<FormInstance>();
const [visible, setVisible] = useState(false)
return (
<>
<Button ref={inputRef} onClick={() => setVisible(true)}></Button>
<Modal
visible={visible}
onOk={() => formRef.current?.submit()}
onCancel={() => setVisible(false)}
>
<Form ref={formRef}/>
</Modal>
</>
)
}
自定义hook
用于提取两个函数的共享逻辑。实际上是一个函数,名称use开头,函数内部可以调用其他hook。
两个组件中使用相同的hook不会共享state。 自定义hook是一种重用 状态逻辑 的机制,所以每次使用时,其中的 state 和 副作用都是完全隔离的。
import { useState, useEffect } from 'react'
export default {
function useFriendStatus(friendId) {
const [isOnline, setIsOnline] = useState(null)
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline)
}
ChatAPI.subscribeToFriendStatus(friendId, handleStatusChange)
return () => {
ChatAPI.unsubscribeFromFriendStatus(friendID, handleStatusChange);
}
})
return isOnline
}
}
// ---- 使用 -----
function FriendListItem(props) {
const isOnline = useFriendStatus(props.friend.id)
return (
<li style={{color: isOnline ? 'green' : 'black'}}>
{{props.friend.name}}
</li>
)
}
function FriendStatus(props) {
const isOnline = useFriendStatus(props.friend.id)
if (isOnline === null) {
return 'loading...'
}
return isOnline ? 'Online' : 'Offline'
}
hook 规则
- 在最顶层使用hook 不要在循环、条件或者嵌套函数中使用
- 只在 React函数 中调用 hook
useEffect(() => {
// 判断放在useEffect内部
if (name !== '') {
localStorage.setItem('formDate', name)
}
})
多个hook传递信息
const friendList = [
id: 1, name: 'AAA',
id: 2, name: 'BBB',
id: 3, name: 'CCC'
]
function ChatReceiptPicker() {
const [receiptId, setReceiptId] = useState(1)
// 2. 将新的 ReceiptId 传入,获得新的在线情况
const isReceiptOnline = useFriendStatus(receiptId)
return (
<>
<Circle color={isReceiptOnline ? 'green' : 'red'}/>
// 1. 每次更改获得更改后的数据,通过 setReceipt 更新 receiptId
<select value={receiptId} onChange={e => setReceiptId(Number(e.target.value))}>
{friendList.map(friend => (
<option key={friend.id} value={friend.id}>{friend.name}</option>
))}
</select>
</>
)
}
其他hook
useContext
const value = useContext(myContext)接受一个
context对象(React.createContext的 返回值)并返回该context的当前值。当前的context值 由上层组件中距离当前组件最近的<MyContext.Provider>的valueprop 决定。
useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a,b), [a,b])返回一个 memoized 值
把“创建”函数和依赖项数组作为参数传入 useMemo,它仅在某个依赖项发生变化时重新计算返回值。避免在每次渲染时都进行高开销的计算。
useMemo和useEffect的区别:
useMemo中只执行与渲染有关的操作,而useEffect中执行副作用这类的操作。