微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

useRef、useMemo、useCallback 挂钩的生产用例是什么?

如何解决useRef、useMemo、useCallback 挂钩的生产用例是什么?

除了在许多 YouTube 教程视频中看到的计数器示例之外,useMemouseCallback实际/真实世界用例是什么?

此外,我只看到了 useRef 钩子的输入焦点示例。

分享您为这些钩子找到的其他用例。

解决方法

useRef

语法: const refObject = useRef(initialValue);

它只是返回一个普通的 JavaScript 对象。可以根据需要多次访问和修改它的值(可变性),而无需担心“重新渲染”。

它的值将持久化(不会被重置为 initialValue 不像函数组件中定义的普通*对象;它持久化是因为 useRef对象,而不是在后续渲染中创建一个新对象)在组件生命周期内。

如果您在控制台上编写 const refObject = useRef(0) 并打印 refObject,您将看到日志对象 - { current: 0 }

*普通对象 vs refObject,示例:

function App() {
  const ordinaryObject = { current: 0 } // It will reset to {current:0} at each render
  const refObject = useRef(0) // It will persist (won't reset to the initial value) for the component lifetime
  return <>...</>
}

一些常见用途,示例:

  1. 要访问 DOM<div ref={myRef} />
  2. 存储可变值,如 instance variable (in class)
  3. 渲染counter
  4. setTimeout / setInterval 中使用的值,没有 stale closure 问题。

useMemo

语法const memoizedValue = useMemo(() => computeExpensiveValue(a,b),[a,b]);

它返回一个 memoized 。这个钩子的主要目的是“性能优化”。在需要时谨慎使用它来优化性能。

它接受两个参数——“create”函数(它应该返回一个要记忆的值)和“dependency”数组。只有当依赖项之一发生变化时,它才会重新计算记忆值。

一些常见用途,示例:

  1. 在渲染时优化昂贵的计算(例如对数据进行排序、过滤、更改格式等操作)

未记忆的示例:

function App() {
  const [data,setData] = useState([.....])

  function format() {
    console.log('formatting ...') // this will print at every render
    const formattedData = []
    data.forEach(item => {
      const newItem = // ... do somthing here,formatting,sorting,filtering (by date,by text,..) etc
      if (newItem) {
        formattedData.push(newItem)
      }
    })
    return formattedData
  }

  const formattedData = format()

  return <>
    {formattedData.map(item => <div key={item.id}>
      {item.title}
    </div>)}
  </>
}

记忆化示例:

function App() {
  const [data,setData] = useState([.....])

  function format() {
    console.log('formatting ...') // this will print only when data has changed
    const formattedData = []
    data.forEach(item => {
      const newItem = // ... do somthing here,..) etc
      if (newItem) {
        formattedData.push(newItem)
      }
    })
    return formattedData
  }

  const formattedData = useMemo(format,[data])

  return <>
    {formattedData.map(item => <div key={item.id}>
      {item.title}
    </div>)}
  <>
}

useCallback

语法const memoizedCallback = useCallback(() => { //.. do something with a & b },b])

它返回一个 memoized 函数(或回调)。

它接受两个参数——“函数”和“依赖”数组。只有当依赖项之一发生变化时,它才会返回新的,即重新创建的函数,否则它将返回旧的,即记忆的。

一些常见用途,示例:

  1. 将记忆化的函数传递给子组件(使用浅等值 - React.memo 使用 shouldComponentUpdateObject.is 进行优化)以避免由于函数作为 props 传递而导致子组件不必要的重新渲染。

示例 1,没有 useCallback

const Child = React.memo(function Child({foo}) {
  console.log('child rendering ...') // Child will rerender (because foo will be new) whenever MyApp rerenders
  return <>Child<>
})

function MyApp() {
  function foo() {
    // do something
  }
  return <Child foo={foo}/>
}

示例 1,带有 useCallback

const Child = React.memo(function Child({foo}) {
  console.log('child rendering ...') // Child will NOT rerender whenever MyApp rerenders
  // But will rerender only when memoizedFoo is new (and that will happen only when useCallback's dependency would change)
  return <>Child<>
})

function MyApp() {
  function foo() {
    // do something
  }
  const memoizedFoo = useCallback(foo,[])
  return <Child foo={memoizedFoo}/>
}
  1. 将记忆化的函数作为其他钩子中的依赖项传递。

示例 2,没有 useCallback,差(但是 eslint-plugin-react-hook 会警告您纠正它):

function MyApp() {
  function foo() {
    // do something with state or props data
  }
  useEffect(() => {
    // do something with foo
    // maybe fetch from API and then pass data to foo
    foo()
  },[foo])
  return <>...<>
}

示例 2,带有 useCallback,良好:

function MyApp() {
  const memoizedFoo = useCallback(function foo() {
    // do something with state or props data
  },[ /* related state / props */])

  useEffect(() => {
    // do something with memoizedFoo
    // maybe fetch from API and then pass data to memoizedFoo
    memoizedFoo()
  },[memoizedFoo])
  return <>...<>
}

这些钩子规则或实现可能会在未来发生变化。因此,请务必检查文档中的 hooks reference。此外,重要的是要注意 eslint-plugin-react-hook 关于依赖项的警告。如果省略这些钩子的任何依赖,它会指导你。

,

我想补充一点,对于useMemo,我通常在想同时结合useState 和useEffect 时使用它。例如:

...
const [data,setData] = useState(...);
const [name,setName] = useState("Mario");
// like the example by ajeet,for complex calculations
const formattedData = useMemo(() => data.map(...),[data])
// or for simple state that you're sure you would never modify it directly
const prefixedName = useMemo(() => NAME_PREFIX + name,[name]);

我不知道是否会出现性能问题,因为文档指出 useMemo 应该用于昂贵的计算。但我相信这比使用 useState 更干净

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?