• React 其他常用Hooks


    1. useImperativeHandle

    • 在react中父组件可以通过forwardRef将ref转发到子组件;
    • 子组件拿到父组件创建的ref,绑定到自己的某个元素;
    forwardRef的做法本身没有什么问题,但是我们是将子组件的DOM直接暴露给了父组件,某下情况可能造成不可控的问题, 父组件可以拿到DOM后进行任意的操作
    通过 useImperativeHandle:
    可以只暴露固定的操作, 通过useImperativeHandle的Hook,将传入的ref和useImperativeHandle第二个参数返回的对象绑定到了一起,在父组件调用子组件的方法时,通过自定义实现,让父组件使用返回的对象;
    1. import React, { memo, useRef, forwardRef, useImperativeHandle } from 'react'
    2. const HelloWorld = memo(forwardRef((props, ref) => {
    3. const inputRef = useRef()
    4. // 子组件对父组件传入的ref进行处理
    5. useImperativeHandle(ref, () => {
    6. return {
    7. focus() {
    8. console.log("focus")
    9. inputRef.current.focus()
    10. },
    11. setValue(value) {
    12. inputRef.current.value = value
    13. }
    14. }
    15. })
    16. return <input type="text" ref={inputRef}/>
    17. }))
    18. const App = memo(() => {
    19. const titleRef = useRef()
    20. const inputRef = useRef()
    21. function handleDOM() {
    22. // console.log(inputRef.current)
    23. inputRef.current.focus()
    24. // inputRef.current.value = ""
    25. inputRef.current.setValue("哈哈哈")
    26. }
    27. return (
    28. <div>
    29. <h2 ref={titleRef}>哈哈哈h2>
    30. <HelloWorld ref={inputRef}/>
    31. <button onClick={handleDOM}>DOM操作button>
    32. div>
    33. )
    34. })
    35. export default App

    2. useLayoutEffect

    useLayoutEffect看起来和useEffect非常的相似,事实上他们也只有一点区别而已:

    • useEffect会在渲染的内容更新到DOM上后执行,不会阻塞DOM的更新;
    • useLayoutEffect会在渲染的内容更新到DOM上之前执行,会阻塞DOM的更新;

    如果我们希望在某些操作发生之后再更新DOM,那么应该将这个操作放到useLayoutEffect。

    3. redux hooks

    redux开发中,为了让组件和redux结合起来,我们使用了react-redux中的connect:
    • 这种方式必须使用高阶函数结合返回的高阶组件;
    • 必须编写:mapStateToProps和 mapDispatchToProps映射的函数;

    Redux7.1开始,提供了Hook的方式,我们再也不需要编写connect以及对应的映射函数

    useSelector的作用是将state映射到组件中:

    • 参数一:将state映射到需要的数据中;
    • 参数二:可以进行比较来决定是否组件重新渲染(react-redux中提供了shallowEqual进行比较);
    useDispatch: 直接获取dispatch函数,之后在组件中直接使用即可;
    1. import React, { memo } from 'react'
    2. import { useSelector, useDispatch, shallowEqual } from "react-redux"
    3. import { addNumberAction, changeMessageAction, subNumberAction } from './store/modules/counter'
    4. // memo高阶组件包裹起来的组件有对应的特点: 只有props发生改变时, 才会重新渲染
    5. const Home = memo((props) => {
    6. const { message } = useSelector((state) => ({
    7. message: state.counter.message
    8. }), shallowEqual) // shallowEqual优化,只有当组件内使用的state.message改变时重新加载 不会由于父组件更新了state的其他参数重新渲染
    9. const dispatch = useDispatch()
    10. function changeMessageHandle() {
    11. dispatch(changeMessageAction("你好啊, 师姐!"))
    12. }
    13. console.log("Home render")
    14. return (
    15. <div>
    16. <h2>Home: {message}h2>
    17. <button onClick={e => changeMessageHandle()}>修改messagebutton>
    18. div>
    19. )
    20. })
    21. const App = memo((props) => {
    22. // 1.使用useSelector将redux中store的数据映射到组件内
    23. const { count } = useSelector((state) => ({
    24. count: state.counter.count
    25. }), shallowEqual)
    26. // 2.使用dispatch直接派发action
    27. const dispatch = useDispatch()
    28. function addNumberHandle(num, isAdd = true) {
    29. if (isAdd) {
    30. dispatch(addNumberAction(num))
    31. } else {
    32. dispatch(subNumberAction(num))
    33. }
    34. }
    35. console.log("App render")
    36. return (
    37. <div>
    38. <h2>当前计数: {count}h2>
    39. <button onClick={e => addNumberHandle(1)}>+1button>
    40. <button onClick={e => addNumberHandle(6)}>+6button>
    41. <button onClick={e => addNumberHandle(6, false)}>-6button>
    42. <Home/>
    43. div>
    44. )
    45. })
    46. export default App

    4. useTransition

    返回一个状态值表示过渡任务的等待状态,以及一个启动该过渡任务的函数。
    打个比方:搜索过滤,在输入框输入时,对于上w条数据时,会存在卡顿,是由于在搜索的输入事件中,event.target.value更新与过滤出来的数据同时更新,导致输入存在卡顿原因。通过useTransition 在告诉react对于某部分任务的更新优先级较低,可以稍后进行更新。
    useTransition返回两个参数。
    1. import React, { memo, useState, useTransition } from 'react'
    2. import namesArray from './namesArray'
    3. const App = memo(() => {
    4. const [showNames, setShowNames] = useState(namesArray)
    5. const [ pending, startTransition ] = useTransition()
    6. function valueChangeHandle(event) {
    7. startTransition(() => {
    8. const keyword = event.target.value
    9. const filterShowNames = namesArray.filter(item => item.includes(keyword))
    10. setShowNames(filterShowNames)
    11. })
    12. }
    13. return (
    14. <div>
    15. <input type="text" onInput={valueChangeHandle}/>
    16. <h2>用户名列表: {pending && <span>data loadingspan>} h2>
    17. <ul>
    18. {
    19. showNames.map((item, index) => {
    20. return <li key={index}>{item}li>
    21. })
    22. }
    23. ul>
    24. div>
    25. )
    26. })
    27. export default App
  • 相关阅读:
    程序员的这些冷笑话,有点意思!
    GZ033 大数据应用开发赛题第03套
    JAVA应用导致 CPU 100% 占用问题排查
    【无标题】
    敏捷管理的4价值观12准则
    【Linux内核】线程设置 线程调度 线程通信
    欧盟《数据治理法》说明
    Chiplet解决芯片技术发展瓶颈
    Caffe在Linux下的安装,编译,实验
    线性代数 | 矩阵运算 加减 数乘 矩阵的幂运算
  • 原文地址:https://blog.csdn.net/weixin_47342624/article/details/134269146