xgqfrms™, xgqfrms® : xgqfrms's offical website of cnblogs! xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!

dive into React Hooks useRef All In One

dive into React Hooks useRef All In One

useRef

https://beta.reactjs.org/apis/react#refs

https://reactjs.org/docs/hooks-reference.html#useref

https://reactjs.org/docs/hooks-faq.html#is-there-something-like-instance-variables

function Timer() {
  const intervalRef = useRef();

  useEffect(() => {
    const id = setInterval(() => {
      // ...
    });
    intervalRef.current = id;
    return () => {
      clearInterval(intervalRef.current);
    };
  });

  // ...
  function handleCancelClick() {
    clearInterval(intervalRef.current);
  }
  // ...
}


https://reactjs.org/docs/hooks-faq.html#how-to-create-expensive-objects-lazily

lazy initialization,once

react 性能优化

function Table(props) {
  // ⚠️ createRows() is called on every render  ❌
  const [rows, setRows] = useState(createRows(props.count));
  // ...
}

To avoid re-creating the ignored initial state, we can pass a function to useState:


function Table(props) {
  // ✅ createRows() is only called once
  const [rows, setRows] = useState(() => createRows(props.count));
  // ...
}
 

function Image(props) {
  const ref = useRef(null);
  // ✅ IntersectionObserver is created lazily once
  function getObserver() {
    // ✅ ref.curren
    if (ref.current === null) {
      ref.current = new IntersectionObserver(onIntersect);
    }
    return ref.current;
  }

  // When you need it, call getObserver()
  // ...
}

Refs

https://reactjs.org/docs/refs-and-the-dom.html

https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node

useCallback

function MeasureExample() {
  const [height, setHeight] = useState(0);

  const measuredRef = useCallback(node => {
    if (node !== null) {
      setHeight(node.getBoundingClientRect().height);
    }
  }, []);

  return (
    <>
      <h1 ref={measuredRef}>Hello, world</h1>
      <h2>The above header is {Math.round(height)}px tall</h2>
    </>
  );
}

error

Warning: You are calling ReactDOMClient.createRoot() on a container that has already been passed to createRoot() before. Instead, call root.render() on the existing root instead if you want to update it.

image

https://reactjs.org/docs/react-dom-client.html

https://github.com/reactwg/react-18/discussions/5

demos

import {
  useEffect,
  // useState,
  useRef,
} from "react";
import { createRoot } from 'react-dom/client';
// import ReactDOM from 'react-dom';

export default function Home() {
  const log = console.log;
  // log(`v18 ReactDOM.createRoot =\n`, ReactDOM.createRoot);
  log(`v18 createRoot =\n`, createRoot);
  let root = useRef(null);
  // let root = null;
  useEffect(() => {
    // v18
    console.log(`root =`, root)
    console.log(`root.current =`, root.current)
    if(!root.current) {
      const App = document.getElementById('v18-app');
      // const root = ReactDOM.createRoot(App);
      root.current = createRoot(App);
      // JSX
      root.current.render(<h1>Develop. Preview. Ship. 🚀 React v18 🆕</h1>);
    }
  }, []);
  return (
    <div id="v18-app">...loading</div>
  )
}

Assignments to the 'root' variable from inside React Hook useEffect will be lost after each render.
To preserve the value over time, store it in a useRef Hook and keep the mutable value in the '.current' property.
Otherwise, you can move this variable directly inside useEffect.eslintreact-hooks/exhaustive-deps

https://github.com/facebook/react/issues/14920

refs



©xgqfrms 2012-2021

www.cnblogs.com/xgqfrms 发布文章使用:只允许注册用户才可以访问!

原创文章,版权所有©️xgqfrms, 禁止转载 🈲️,侵权必究⚠️!


posted @ 2022-11-15 17:42  xgqfrms  阅读(170)  评论(2编辑  收藏  举报