Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Anton Korzunov
Anton Korzunov

Posted on • Edited on

     

The same useRef, but it will callback 🤙

For a long while we there were norefs - we had onlyref, which was callback based. Something will set aref by calling it.

classExampleextendsReact.Component{state={ref1:null,}ref2=null;// updating ref1 would trigger update for this componentsetRef1=(ref)=>this.setState(ref1);// updating ref2 would just set itsetRef2=(ref)=>this.ref2=ref;render(){return<divref={ref1}><spanref={ref2}>🤷‍♂️</span></div>}
Enter fullscreen modeExit fullscreen mode

That was what we were doing for ages, untilcreateRef comes to the game.React.createRef is more aboutref2 way - current ref wouldjust set to, well,ref.current.

Keep in mind thatuseRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render.

So -If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to usea callback ref instead. Ie the old way to _ref.

Hooks API Reference

constExample=()=>{const[ref,setRef]=useState(null);constonRefSet=useCallback(ref=>{setRef(ref);ref.current.focus();// a side effect!});// well, you can rereturn<divref={onRefSet}>😎</div>}
Enter fullscreen modeExit fullscreen mode

But later you might try to combine ref-refs and callbacks-refs, and... well that's the road to 🔥hell🔥.

In addition - there isuseImperativeHandle whichpartially could controlref propagation, but every time I was used to use it - it was just a 💩disaster💩.

functionFancyInput(props,ref){constinputRef=useRef(null);useImperativeHandle(ref,()=>({focus:()=>{inputRef.current.focus();// it just does not usually works :P}}));return<inputref={inputRef}.../>;}FancyInput=forwardRef(FancyInput);
Enter fullscreen modeExit fullscreen mode

LET'S FIX IT!

Introducinguse-callback-ref - the samecreateRef anduseRef, but with callback built in.

import{useCallbackRef}from'use-callback-ref';constExample=()=>{constref=useCallbackRef(null,ref=>ref&&ref.focus());// that's allreturn<divref={ref}>😎</div>}
Enter fullscreen modeExit fullscreen mode

It's literally the old goodref with anon-change callback, nothing more.

Why not to use callback-based ref? Well, it's much easier to handle one interface, which would be accessible thought all components that ref would be passed, well, thought - while withsetRef onlycallback would be visible for transitional components. However, that could be a good from isolation point of view.

This simple approach could also help withuseImperativeHandle case:

functionFancyInput(props,ref){constinputRef=useCallbackRef(null,(newValue)=>{// notice - this code is __isolated__, and you can move it off this componentref.current={focus:()=>newValue.focus()}// as long as you don't need to use callback-ref anymore - we could simply this case.});return<inputref={inputRef}.../>;}FancyInput=forwardRef(FancyInput);
Enter fullscreen modeExit fullscreen mode

So - Keep in mind thatuseRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node,you may want to use a useCallbackRef instead.

  • 300b, and IE11 support
  • based on getters and setters, no Proxies involved

Try it now(codesandbox demo), and call me back later -https://github.com/theKashey/use-callback-ref

And there is the second part of this article


Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
joelstransky profile image
Joel Stransky
Front End Developer, Game Developer, Game Artist, UI/UX Designer, Graphic Artist, Dad
  • Location
    Las Vegas
  • Work
    Senior Developer
  • Joined

This completely solved my issue with connecting Greensock to React-Pixi components.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Reinventing the wheels.
  • Location
    Sydney
  • Work
    Foreign Contaminant at Atlassian
  • Joined

More fromAnton Korzunov

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp