Refs is a technical term
Provides a way to access DOM or React elements
In a nutshell, it provides a way to manually retrieve and manipulate the DOM directly
For example, input element focus
File uploading function, etc
It’s the REF attribute that does the work
Noun explanation
- ClassComponent class components
- FunctionComponent FunctionComponent
- The React Hook Hook
- Callback ref Callback ref
The attribute value type varies depending on the node type to which the REF is bound
- The ref binding node is of type DOM element and ref represents the concrete DOM element
- The ref binding node type is ClassComponent and ref represents the ClassComponent (instance).
- The ref binding node type is FunctionComponent. Note that it cannot be bound directly
- Because it’s not a DOM or ClassComponent
- itself
props
Does not exist by defaultref
Through theReact.forwardRef
The function must bind the DOM or ClassComponent inside it.
Create ref mode
In addition to the callback ref
Create a REF reference either way
Both contain the current attribute, which contains the ref specific value
- The React. CreateRef way
- For ClassComponent, not recommended for FunctionComponent, in
FunctionComponent
Rerender is initialized to create a new ref reference (see the difference comparison below for details) - The parameter cannot be passed
current
Properties inTypescript
The tips forread-only
createRef<T>
Generic functions have no default value and are set tounknow
- For ClassComponent, not recommended for FunctionComponent, in
- The React. UseRef way
React Hook
One, followHookRules, for FunctionComponent or other hooks, are called at the top level of function scope- Can be used for data storage or performance optimization to save data to
current
On the properties - The parameter type can be arbitrary
- Create once, update render not create only reuse
useRef<T = undefined>
The default value for generic functions isundefined
current
Property value changes cannot be detected and do not trigger the componentrender
View update
- callback refway
- Resolved that ref value changes cannot be monitored
- The ClassComponent inline binding or FunctionComponent binding is called twice when updated again, printing the first value as
null
, the second time is the specific bindingnode
React empties the old ref and sets the new one - In ClassComponent,
callback ref
Class when bound to an inline functionrender
Call it once, againrender
Call twice
export default class Child extends React.PureComponent { state = { a: 100 } constructor(props: any) { super(props) } onCount() { this.setState({ a: Math.random() }) } render() { return ( <div> <p ref={(node: any) = >Log (node)}}>{this.state. A} {this.state.</p> <button className="btn btn-primary" onClick={this.onCount.bind(this)}>click</button> </div>)}}Copy the code
callback ref
Bind instance method, initializerender
Call it once, againrender
Don’t call
export default class Child extends React.PureComponent { state = { a: 100 } cbRef: (node: any) = > void constructor(props: any) { super(props) this.cbRef = (node: any) = > { // Initialize and re-render updates, print only once // Result: node object console.log(node) } } onCount() { this.setState({ a: Math.random() }) } render() { return ( <div> <p ref={this.cbRef}>{this.state.a}</p> <button className="btn btn-primary" onClick={this.onCount.bind(this)}>click</button> </div>)}}Copy the code
- In FunctionComponent,
callback ref
Whether the function is inline or not, initialize it and print it once, render it again and print it twicefunction User(_props: any) { let [data] = useState({ foo: 1 }) const [count, setCount] = useState(0) const renderRef = (node: any) = > { // Initialize to print the result once: node object // Next render update prints two results: the first null and the second node object console.log(node) } return ( <> <h3>{data.foo}</h3> <p ref={renderRef}>count: {count}</p> <button className="btn btn-primary" onClick={()= > setCount(count + 1)}>click me</button> </>)}export default User Copy the code
Ref forwarding forwardRef
FunctionComponent has no ref attribute
The parent component cannot get DOM elements directly by ref referencing FunctionComponent components
Utilize the forwardRef forwarding feature
The forwarded FunctionComponent component has the ref attribute
Bind the parent component ref to the DOM element
In the parent component, you can get the child’s specific DOM element for manipulation
function InputChild(props: any) {
return (
<input type="text" ref={props.inputRef} className="form-control" placeholder="Say something." />)}const ForwardInput = forwardRef((props, ref: any) = > <InputChild inputRef={ref} />)
function User(_props: any) {
const ref = useRef<HTMLInputElement>()
return (
<>{/* The parent component sets the ref attribute by forwarding the returned component through InputChild */} {/* The parent component clicks the button to set the focus of the input element */}<ForwardInput ref={ref} />
<button className="btn btn-primary" onClick={()= >ref? .current? .focus()}>input focus</button>
</>)}export default User
Copy the code
Compare createRef and useRef in FunctionComponent
As shown above:
CreateRef is always null every time it renders new
UseRef is only created once and reused during rendering, so it references the same P element
The FunctionComponent recommends useRef
The source code is as follows:
function User(_props: any) {
const ref = useRef(null)
const ref2 = createRef<HTMLParagraphElement>()
const [count, setCount] = useState(0)
useEffect(() = > {
}, [count])
console.log(count)
console.log('useRef:', ref, 'createRef:', ref2)
return (
<>
<h3>{count}</h3>
<p ref={ref}>useRef p</p>
<p ref={ref2}>createRef p</p>
<button className="btn btn-primary" onClick={()= > setCount(count + 1)}>click count</button>
</>)}export default User
Copy the code