重学前端-Hooks

重学前端-Hooks

更新日期:11-7

第一次更新:11-7

第二次更新:11-13

第三次更新:11-14

1、React Hooks 介绍

1、React Hooks 是⽤来做什么的

对函数型组件进⾏增强, 让函数型组件可以存储状态, 可以拥有处理副作⽤的能⼒.
让开发者在不使⽤类组件的情况下, 实现相同的功能.

2、React Hooks 使⽤

1、useState说明

使用闭包来实现保存数据状态,页面重新渲染时状态保持不变

  • 接收唯⼀的参数即状态初始值. 初始值可以是任意数据类型.
  • 返回值为数组. 数组中存储状态值和更改状态值的⽅法. ⽅法名称约定以set开头, 后⾯加上状态名称.
  • ⽅法可以被调⽤多次. ⽤以保存不同状态值.
  • 参数可以是⼀个函数, 函数返回什么, 初始状态就是什么, 函数只会被调⽤⼀次(组件第一次被渲染的时候得到执行), ⽤在初始值是动态值的情况.

setState会用新的状态值替换老的状态值

只修改对象中age的做法

const [person,setPerson] = useState({name:'李四',age:20})
<button onClick = {() => setPerson({...person,age:30})}>setPerson</button>

useState初始值传递函数的情况

传递函数只会被执行一次

const [count, setCount] = useState(()=>{
  return props.count || 0
})

设置状态值方法的特性

设置状态值的方法可以是一个值也可以是一个函数(带有一个形参也就是保存的状态值)

设置状态的方法本身是异步的

异步解决方案:

function handleCount(){
  setCount(count =>{
    const newCount = count +1
    document.title = newCount
    return newCount
  })
}

function handleCount(){
  setCount(count =>{
    document.title = count +1
    return count +1
  })
}

2、useReducer()

useState()拓展

3、useContext()

在跨组件层级获取数据时简化获取数据的代码

const countContext  = createContext();
function App(){
  return <countContext.Provide value={100}>
    <Foo />
    </countContext.Provide>
}
function Foo(){
  const value = useContext(countContext);
  return <div>{value}</>
}

3、useEffect

让函数式组件拥有处理副作用的能力,类似于生命周期

解决问题:按照用途将代码进行分类(将一组相干的逻辑归置到同一个副作用函数中)

简化重复代码,使组件内部代码更加清晰

//组件挂载完成之后执行,组件更新完成之后执行
useEffect(()=>{
  console.log('组件挂载完成,更新完成')
})
//组件挂载完成之后执行一次
useEffect(()=>{
  console.log('组件挂载完成')
},[])
//组件被卸载之前执行
useEffect(()=>{
  return ()=>{
    console.log('组件被卸载')
  }
},[])
//卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('root'))

案例:

//为window对象添加滚动事件
//组件挂载完成绑定,在组件卸载之前解绑
useEffect(()=>{
  window.addEventListener('scroll',onScroll)
  return()=>{
    window.removeEventListener('scroll',onScroll)
  }
},[])
//设置定时器让count数值每隔一秒增加1
useEffect(()=>{
  const timerId = setInterval(()=>{
    setCount(()=>count+1)
  },1000)
  return ()=>{
    clearInterval(timerId)
  }
},[])

useEffect第二个参数:只有指定数据发生变化时触发effect

useEffect结合异步函数

useEffect中的参数函数不能是异步函数,因为useEffect函数要返回清理资源的函数,如果是异步函数就变成返回Promise

useEffect(()=>{
  (async function(){
    let res = await getData()
  	}
  )
},[])

4、useMemo

1、useMemo

类似于vue中的计算属性,用于监测某个值的变化,根据变化值计算新值,返回计算出来的新值

特点:会缓存结果(缓存值),如果监测值没有发生变化,即使组件重新渲染,也不会重新计算

传入两个参数,要执行的函数以及监测的值,当监测的值发生改变后执行回调函数

2、memo方法

如果组件数据没有发生变化,阻止组件更新,类似PureComponent和shouldComponentUpdate

memo方法传入一个function返回一个新组件

5、useCallback

性能优化,缓存函数,使组件渲染时得到相同的函数实例

说明:当父组件的值发生改变,父组件重新渲染,组件重新渲染生成了不同的函数实例,也就是说每一次给子组件传递的都是不同的函数,导致子组件重新渲染,父组件中的函数实例和上一次组件中调用的函数实例不是同一个。相当于给子组件传递了一个不同的函数,函数的变化导致子组件又发生重新渲染,使用callback优化使函数每次得到的都是同一个实例

一般场景:父组件给子组件传递函数做一层callback优化

6、useRef

1、基本使用

获取DOM元素对象

2、保存数据(跨组件周期)

即使组件重新渲染,保存的数据仍然存在,保存的数据被更改不会触发组件重新渲染

跨组件周期:组件重新渲染不丢失

useState:保存状态数据,当数据发生改变触发组件重新渲染
useRef:不属于状态数据,更改了也不会导致组件重新渲染
//使用场景
// 存在问题:无法清除定时器,在定时器中使用setCount更改页面数据的值,当值发生改变,组件重新渲染,timeId被重新定义,点击按钮清除的就是空的timeId,当组件重新渲染后,timeId已经丢失
function App() {
  const [count, setCount] = useState(0);
  let timeId = null;
  useEffect(() => {
    timeId = setInterval(() => {
      setCount(count => count + 1);
    }, 1000);
  }, []);
  const stopCount = () => {
    clearInterval(timeId);
  };
  return (
    <div>
      {count}
      <button onClick={stopCount}>停止</button>
    </div>
  );
}
// 解决方案,当组件重新渲染后,timeId不被重置,即保存timeId
function App() {
  const [count, setCount] = useState(0);
  let timeId = useRef();
  useEffect(() => {
    timeId.current = setInterval(() => {
      setCount(count => count + 1);
    }, 1000);
  }, []);
  const stopCount = () => {
    clearInterval(timeId.current);
  };
  return (
    <div>
      {count}
      <button onClick={stopCount}>停止</button>
    </div>
  );
}

3、⾃定义 Hook

  • 自定义hook使标准的封装和共享逻辑的方式
  • 自定义hook是一个函数,以use开头
  • 自定义hook其实就是逻辑和内置hook的组合
//自定义hook复用逻辑
function useUpdateInput(initialValue) {
  const [value, setValue] = useState(initialValue);
  return {
    value,
    onChange: event => setValue(event.target.value),
  };
}
function App() {
  const usernameInput = useUpdateInput('');
  const passwordInput = useUpdateInput('');
  const submitForm = event => {
    event.preventDefault();
    console.log(usernameInput.value);
    console.log(passwordInput.value);
  };
  return (
    <form onSubmit={submitForm}>
      <input type='text' name='username' {...usernameInput} />
      <input type='password' name='password' {...passwordInput} />
      <input type='submit' />
    </form>
  );
}

4、React 路由 Hooks

react-router-dom路由提供的钩子函数

实现目的:获取路由信息

useHistory

useLocation

useRouteMatch

useParams(常用)

5、React Hooks 原理分析

1、useState实现原理
2、useEffect实现原理
3、useReducer实现原理
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值