In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-27 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces what the Ref in React is. It is very detailed and has certain reference value. Friends who are interested must finish reading it.
Intro
In React projects, there are many scenarios that need to use Ref. For example, use the ref attribute to get the DOM node and get the ClassComponent object instance; use useRef Hook to create a Ref object to solve the problem that you can't get the latest state like setInterval; you can also call the React.createRef method to manually create a Ref object.
Although Ref is easy to use, it is hard to avoid problems in actual projects. This article will sort out various problems related to Ref from the perspective of source code and sort out what is going on behind the API related to ref. Reading this article may give you a better understanding of Ref.
Type declarations related to Ref
First of all, ref is the abbreviation of reference, that is, reference. Several Ref-related types can be found in react's type declaration file, and they are listed here.
RefObject/MutableRefObjectinterface RefObject {readonly current: t | null;} interface MutableRefObject {current: t;}
When using useRef Hook, RefObject/MutableRefObejct is returned. Both types define an object structure of {current: t}. The difference is that the current property of RefObject is read-only. If you modify refObject.current,Typescript, you will warn ⚠️.
Const ref = useRef (null) ref.current =''/ / Error
TS error: cannot be assigned to "current" because it is read-only.
Look at the definition of the useRef method, where function overloading is used, returning RefObject if the generic parameter T does not contain null, and MutableRefObject if it contains null.
Function useRef (initialValue: t): MutableRefObject;function useRef (initialValue: t | null): RefObject
So if you want to create a ref object whose current property is modifiable, you need to add | null.
Const ref = useRef (null) ref.current =''/ / OK
A RefObject is also returned when the React.createRef () method is called.
CreateRef
Export function createRef (): RefObject {const refObject = {current: null,}; if (_ _ DEV__) {Object.seal (refObject);} return refObject;}
RefObject/MutableRefObject was added in version 16.3, and if you use an earlier version, you need to use Ref Callback.
RefCallback
To use Ref Callback is to pass a callback function. When react is called back, the corresponding instance will be passed back, and you can save it for calling. The type of this callback function is RefCallback.
Type RefCallback = (instance: t | null) = > void
Example of using RefCallback:
Import React from 'react'export class CustomTextInput extends React.Component {textInput: HTMLInputElement | null = null; saveInputRef = (element: HTMLInputElement | null) = > {this.textInput = element;} render () {return ();}} Ref/LegacyRef
In the type declaration, there are also Ref/LegacyRef types, which are used to refer generally to Ref types. LegacyRef is a compatible version, and in previous versions ref can also be a string.
Type Ref = RefCallback | RefObject | null;type LegacyRef = string | Ref
Having understood the types related to Ref, it is easier to write Typescript.
The transmission of Ref special props
When using ref on the JSX component, we set a Ref to the ref property. We all know the syntax of jsx, which will be compiled into createElement by tools such as Babel.
/ / jsx// compiled toReact.createElement (App, {ref: ref, id: "my-app"})
Ref looks like any other prop, but if you try to print props.ref inside a component, it's undefined. And the dev environment console gives a hint.
Trying to access it will result in undefined being returned. If you need to access the same value within the child component, you should pass it as a different prop.
What did React do to ref? You can see in the ReactElement source code that ref is RESERVED_PROPS, and key also has this treatment, and they are all specially processed, extracted from props and passed to Element.
Const RESERVED_PROPS = {key: true, ref: true, _ _ self: true, _ _ source: true,}
So ref is a "props" that will be specially treated.
ForwardRef
Prior to version 16.8.0, Function Component was stateless and only based on the props render passed in. With Hook, you can not only have internal state, but also expose methods for external calls (with the help of forwardRef and useImperativeHandle).
If you directly use a Function Component to use the ref,dev environment, the console will alarm, indicating that you need to wrap it with forwardRef.
Function Input () {return} const ref = useRef ()
Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef ()?
What is forwardRef? Take a look at the source code ReactForwardRef.js to fold up the code related to _ _ DEV__, which is just a very simple high-level component. Receive a FunctionComponent of render, wrap it around and define $$typeof as REACT_FORWARD_REF_TYPE,return back.
Trace the code to find resolveLazyComponentTag, where $$typeof will be parsed into the corresponding WorkTag.
The WorkTag corresponding to REACT_FORWARD_REF_TYPE is ForwardRef. Then ForwardRef enters the logic of updateForwardRef.
Case ForwardRef: {child = updateForwardRef (null, workInProgress, Component, resolvedProps, renderLanes,); return child;}
This method calls the renderWithHooks method again, passing in ref in the fifth parameter.
NextChildren = renderWithHooks (current, workInProgress, render, nextProps, ref, / / here renderLanes,)
Continue to trace the code, enter the renderWithHooks method, and you can see that ref is passed as the second parameter of Component. Here we can understand where the second parameter ref of the forwardRef-wrapped FuncitonComponent comes from (compared to ClassComponent contructor, the second parameter is Context).
Knowing how to pass ref, the next question is how ref is assigned.
Assignment of ref
The breakpoint (assign a RefCallback to the ref and break the point in the callback) is traced to the code commitAttachRef, in which it determines whether the ref of the Fiber node is function or RefObject, and handles the instance according to the type. If the Fiber node is HostComponent (tag = 5), which is the DOM node, instance is the DOM node; and if the Fiber node is ClassComponent (tag = 1), instance is the object instance.
Function commitAttachRef (finishedWork) {var ref = finishedWork.ref; if (ref! = = null) {var instanceToUse = finishedWork.stateNode; if (typeof ref = 'function') {ref (instanceToUse);} else {ref.current = instanceToUse;}
The above is the assignment logic for ref in HostComponent and ClassComponent. For components of type ForwardRef, it is another code, but the behavior is basically the same. You can see imperativeHandleEffect here.
Next, let's continue to dig into the React source code to see how useRef is implemented.
Internal implementation of useRef
Locate the code ReactFiberHooks of the useRef runtime by tracking the code
There are two methods, mountRef and updateRef, which, as the name implies, correspond to ref operations on Fiber nodes mount and update.
Function updateRef (initialValue: t): {| current: t |} {const hook = updateWorkInProgressHook (); return hook.memoizedState;} function mountRef (initialValue: t): {| current: t |} {const hook = mountWorkInProgressHook (); const ref = {current: initialValue}; hook.memoizedState = ref; return ref;}
When you can see the mount, useRef creates a RefObject and returns it directly when it is assigned to hook's memoizedState,update.
Different Hook memoizedState saves different content. State information is saved in useState, effect object is saved in useEffect, and ref object is saved in useRef.
Behind the mountWorkInProgressHook,updateWorkInProgressHook method is a linked list of Hooks, and every time render useRef can retrieve the same memoizedState object without modifying the linked list, it's as simple as that.
Application: merge ref
So far, we have learned about the transfer and assignment logic of ref in React, as well as the source code related to useRef. Use an application question to consolidate the above knowledge points: there is an Input component, which needs to access the DOM node through innerRef HTMLInputElement inside the component, and also allows the external ref of the node, how to implement it?
Const Input = forwardRef ((props, ref) = > {const innerRef = useRef (null) return ()})
Consider the code above. How to write it.
= answer split line =
By learning about the internal implementation of Ref, it is obvious that we can create a RefCallback here and assign values to multiple ref in it.
Export function combineRefs (refs: Array): React.RefCallback {return value = > {refs.forEach (ref = > {if (typeof ref = 'function') {ref (value);} else if (ref! = = null) {ref.current = value;}});} } const Input = forwardRef ((props, ref) = > {const innerRef = useRef (null) return ()}) these are all the contents of the article "what is Ref in React". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.