React hooks API小结

文章中的例子戳这里看github

hooks 的规则

  • 只能在最高层级调用hooks,不能在循环, 条件或者嵌套方法中调用。
  • 只能在函数组件中调用Hooks, 不能在普通的函数方法中调用(自定义Hook除外)。

hooks是要能够重用stateful logic,即控制state的逻辑,而不是state本身。实际上,任何对hook的调用都会有完全独立的state,所以你甚至可以在一个组件中重用相同的组件Hook

setState

建议根据哪些值是一起变化的,将state拆分成多个小的state。而不是一上来就设一个大的复杂state。

const [state, setState] = useState(initialState)

setState(currentState)
setState((prevState) => f(prevState))
  • 接受一个值或者一个函数
  • 是整个替换更新,而不是
    自动Merge,需要解构自己merge(或者使用useReducer)
  • 懒init 如果initialState需要通过复杂计算获得,可以提供一个函数
const [state, setState] = useState(() => {
   
  const initialState = someExpensiveComputation(props)
  return initialState
})
  • 如果update的值跟之前的值相同,React可能会渲染组件本身,但不会渲染子组件和相关的effects。用Object.is来比较二者。
  • 如果在渲染时有昂贵的计算,则用useMemo来优化

useEffect

在函数式组件/render阶段中不允许有状态的改变,订阅,定时器,日志和其他引起副作用的方法。但可以使用useEffect来做这些事情。它与React类中的componentDidMount,componentDidUpdate和componentWillUnmount具有相同的用途,但整合到了单个的API中。

effect可以分为需要清理的和不需要清理的。网络请求,手动修改dom,和打印日志都属于常用的无需清理的effect。

  • 为何useEffect要在组件内部调用?
    函数作用域问题。这样可以直接在effect中获取到state变量,而不需要一个额外的api去获取。这是js的闭包特性决定的。
  • useEffect是不是在每次渲染之后都会运行?是的!默认是在第一次渲染和以后的每次更新都会跑,当然,可以通过传第二个参数来自定义它。与其用mounting, updating这样的术语来描述它,倒不如想成是effects会在每次render之后发生。React保证DOM在运行effects之前已经被更新了。

useEffect(asyncFn, state)
asyncFn会在render已经完成后执行。在纯函数的世界里,这是一个通往命令世界的逃生舱。
asyncFn需要返回一个清理side-effect的函数。该函数会在组件从UI中移除之前运行,以避免内存泄露。
async并不是指传入的第一个参数本身是async的,而是说里面可以声明一个async的函数,再执行它。

useEffect(() => {
   
  const subscription = props.source.subscribe()
  return () => {
   
    subscription.unsubscirbe()
  }
})

effects的时机

为了避免在每次更新的时候都会清理上次、重新订阅,可以注意下effects的时机。不像componentDidMountcomponentDidUpdate, 传给useEffect的函数在布局和绘制(layout and paint)之后被触发,处于一个被延迟的事件中。这样对许多订阅和事件监听都是适用的,但并非所有的effects都可以被稍后执行。例如,一个展现给用户看的DOM更新必须在下一次绘制的时候同步执行,对这类的effects, react提供了一个特别的hook,叫做useLayoutEffect。它有着与useEffect相同的函数签名,只是触发的时机不同。

尽管useEffect会在浏览器绘制之后延迟触发,但是它一定会在下一次的render之前触发。

条件触发一次effect

useEffect的函数接受第二个参数,一个数组,只有里面的值变动了,才会重新重新触发Effect函数。
确保数组中包括了组件的所有会随着时间改变,并被effect使用的props, state值

  • 如果只想触发一次和清理一次(mount and unmont),可以传一个空数组

useContext

const value = useContext(MyContext)

接受一个context对象(从React.createContext)中创建,并返回一个代表当前的context的值,这个值由最近的<MyContext.Provider>的value Prop决定。当该Provider更新的时候,这个hook就会触发一次重新渲染,会根据最近的一次传给MyContext的value属性变化。

useContext(MyContext) 基本与在class中static contextType = MyContext类似,或者类似于<MyContext.Consumer>

useReducer

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

因为可以把dispatch方法传下去代替回调,对触发深层结构更新的组件会有效率上的优化

const initialState = {
   count, 0}

function reducer(state, action) {
   
  switch (action.type) {
   
    case 'increment': return {
   count: state.count +1}
    case 'decrement':
      return</
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值