React Hook学习

Hook

Hook是React16.8的新增特性,它可以让你在不编写class的情况下使用state以及其他的React特性

使用Hook的原因
  1. Hook使你在无需修改组件结构的情况下复用状态逻辑
  2. Hook将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据)
  3. Hook使你更在非class的情况下可以使用更多的React特性,从概念上讲,React组件一直更像是函数。而Hook则拥抱了函数,同时也没有牺牲React的精神原则。Hook提供了问题的解决方案,无需学习复杂的函数式或响应式编程技术
State Hook

useState就是一个Hook,通过在函数组件里调用它来给组件添加一些内部state。React会在重复渲染时保留这个state。useState会返回一对值:当前状态和一个让你更新它的函数。你可以在事件处理函数中或其他一些地方调用这个函数。它类似class组件的this.setState,但是它不会把新的state和旧的state进行合并。useSate唯一的参数就是初始state,这个初始state参数只有在第一次渲染时会被用到。

声明多个state变量

你可以在一个组件中多次使用State Hook

function ExampleWithManyStates(){
	// 声明多个state变量
    const [age, setAge] = useState(42);
    const [fruit, setFruit] = useState('banana');
    const [todos, setTodos] = useState([{text:'Learn Hooks'}])
}
Effect Hook

在React组件中执行数据过滤、订阅或者手动修改过DOM,我们统一把这些操作称为“副作用”或者简称为“作用”

useEffect 就是一个Effect Hook,给函数组件增加了操作副作用的能力。它跟class组件中的componentDidMount、componentDidUpdate和componentWillUnmount具有相同的用途,只不过被合并成了一个API。

当你调用useEffect时,就是在告诉React在完成对DOM的更改后运行你的“副作用”函数,由于副作用函数是在组件内声明的,所以它们可以访问到组件的props和state,默认情况下,React会在每次渲染后调用副作用函数——包括第一次渲染的时候。

副作用函数还可以通过返回一个函数来指定如何“清除”副作用,例如,在组件中使用副作用函数来订阅好友的在线状态,并通过取消订阅来进行清除操作。

Hook 使用规则

Hook就是JavaScript函数,但是使用它们会有两个额外的规则:

  • 只能在函数最外层调用Hook。不要在循环、条件判断或者函数中调用
  • 只能在React的函数组件中调用Hook或自定义Hook中。不要在其他JavaScript函数中调用
自定义Hook

实现组件之间状态逻辑之间的复用,目前有两种主流方案来解决这个问题:高阶组件和render props。自定义Hook可以让你在不断增加组件的情况下达到同样的目的。

其他Hook

除此之外还有一些使用频率较低的但是很有用的Hook。

比如useContext让你不是用组件嵌套就可以订阅React的Context。

另外useReducer可以让你通过reducer来管理组件本地的复杂state。

useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init)

useState的替代方案,它接收一个形如(state,action)=> newState的reducer,并返回当前的state以及与其配套的dispatch方法,在某些场景下,useReducer会比useState更适用,例如state逻辑较复杂且包含多个子值,或者下一个state依赖于之前的state等。并且,使用useReducer还能给那些会触发深更新的组件做性能优化,因为你可以向子组件传递dispatch而不是回调函数。

useRef
const refContainer  = useRef(initialValue)

useRef返回一个可变的ref对象,其.current属性被初始化为传入的参数(initialValue),返回的ref对象在组件的整个生命周期内保持不变。

useImperativeHandle
useImperativeHandle(ref,createHandle,[deps])

useImperativeHandle可以让你在使用ref时自定义暴露给父组件的实例值。在大多数情况下,应当避免使用ref这样的命令式代码。useImperativeHandle应当与forwardRef一起使用:

function FancyInput(props,ref){
    const inputRef = useRef();
    useImperativeHandle(ref,()=>({
        focus:()=>{
            inputRef.current.focus();
        }
    }))
    return <input ref={inputRef} ... ></input>
}
FancyInput = forwardRef(FancyInput)

在上述例子中,渲染< FancyInput ref = {inputRef} />的父组件可以调用inputRef.current.focus()。

useLayoutEffect

其函数签名与useEffect相同,但它会在所有的DOM变更之后同步调用effect。可以使用它来读取DOM布局并同步触发重渲染。在浏览器执行绘制之前,useLayoutEffect内部的更新计划将被同步刷新。

尽可能使用标准的useEffect以避免阻塞视觉更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩浩不睡觉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值