use
Manipulate attributes of components, subcomponents, and elements
In a typical React top-down data flow, props is the only way for the parent and child to interact, and to modify a child component, you need to re-render it using the new props. In some cases, however, you need to force changes to child components and retrieve component properties outside of a typical data flow. The child component being modified may be an instance of the React component or a native HTML element.
Common scenarios:
- How do I get native in a component
HTML
Element attributes, methods? - How do I get attributes and methods of child components from parent components?
- How do I get a native from a child component directly from a parent component
HTML
Element?
There are four ways to create a Ref
React.createRef()
In React 16.3 and later, you can use the React.createref () method in the instance constructor to create a ref and assign it to the custom properties of the instance object so that it can be used throughout the component, It is then appended to the ref attribute of a native HTML element or a Class component.
class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render() { return <div ref={this.myRef} />; }}Copy the code
Callback function mode
React also supports another way to set a REF, called a “callback ref.” It gives you more fine-grained control over when refs are set and released.
Unlike the ref attribute created through createRef(), “callback refs” passes a function that takes an instance object of the component or a native HTML DOM object as a parameter and assigns that parameter to a custom property of the component instance object so that it can be used throughout the component.
class MyComponent extends React.Component { constructor(props) { super(props); this.setMyRef = null; } render() { return < div ref={ (el) => this.setMyRef = el } />; }}Copy the code
React calls the refS callback when a component is mounted and passes in a parameter object. It calls the refs callback again when a component is unmounted and passes in null as a parameter.
The parent component can directly manipulate the attributes of an element in a child component by using a callback function, as described below:
String mode (obsolete, not recommended)
Set the ref attribute directly to a string, obtained through this.refs
const element = <div ref="myRef">string ref</div>
const node = this.refs.myRef
Copy the code
The use of string refs is outdated and problematic
- Need to be
React
Keeping track of currently rendered components is a bit of a drag on performance - When using
render callback
Set for child components when rendering component content in Render Prop moderef
Not available in the parent component, which is misleading.
Class MyComponent extends Component {renderRow = () => {// String ref is bound to the child DataTable instead of the parent MyComponent return <input ref="input" />; Render () {return <DataTable renderRow={this.renderrow} />}} // render() {return <DataTable renderRow={this.renderrow} />}} // render() {render() {return <DataTable renderRow={this.renderrow} />}} // render() {render() {return <DataTable renderRow={this.renderrow} />}} // // This problem can be avoided by setting the callback function,Copy the code
React.useRef()
In React 16.8 and later, we introduced Hooks to set the ref attribute for React elements. Since Hooks can only be used on function components, useRef() can only set the ref attribute for elements in function components.
function FocusInput() {
const inputEl = useRef();
//inputEl.current.focus();
return (
<>
<input ref={inputEl} type="text" />
</>
);
}
Copy the code
CreateRef () is different from useRef()
//useRef()
const inputEl = useRef();
<input ref={inputEl} type="text" />
//createRef()
const inputEl = createRef();
<input ref={inputEl} type="text" />
Copy the code
The React internal method is called and the ref attribute is assigned to an element inside the component. Both methods seem to be used in function components. Why does React have a new API for creating refs?
UseRef returns a mutable ref object whose.current property is initialized as the passed parameter (initialValue). The ref object returned persists throughout the life of the component.
Refs are created using react.createref () and attached to the React element via the ref attribute. When components are constructed, refs are typically assigned to instance properties so that they can be referenced throughout the component.
Creating a ref in both ways in a function component is an example of how to create a ref in both ways
function MyComponent() { console.log("------------------------render--------------------------") const [count, setCount] = useState(0); const createRef = React.createRef(); const useRef = React.useRef(); console.log("createRef", createRef, "useRef",useRef) if (! createRef.current) { createRef.current = count; } if (! useRef.current) { useRef.current = count; } console.log("createRef", createRef, "useRef",useRef) return ( <div> <h3>count: {count}</h3> <button onClick={() => setCount(count + 1)}>add button</button> </div> ); }Copy the code
In the above function component, each state change causes the code within the function to be re-executed; We also know that the ref attribute attached to the element will eventually be reflected in its.current attribute, so will the printed value be different every time the count state changes?
CreateRef generates a new object every time the component is re-rendered, so it does not save the previous current property value; UseRef creates the same object all its life, or operates on the memory address of the same object all its life.
Ref to forward
Going back to the three questions raised at the beginning, the first two scenarios can be directly accessed by setting the ref for the corresponding element or component; So the third question is, how do YOU get native HTML elements in child components directly from the parent component?
Unlike the props property of a component, the ref set in the parent component is not passed through. Instead, it is treated like a key when received by React and does not appear in the props object of a child component: A ref set to a subcomponent is only attached to the current subcomponent, not passed down, and the.current property of the ref object is used to obtain the instance object of the subcomponent. There are currently two ways:
-
The callback ref
function Child(props) { return ( <input ref={props.childRef} /> ); } class MyComponent extends Component { handleClick() { this.childRef. console.dir(this.childRef) } render () { return ( <div> <Child childRef={el => this.childRef = el }></Child> <p onClick={() => this.handleClick()}>MyComponent</p> </div> ); } } Copy the code
For example, if you set a generic childRef property to the Child component in the parent MyComponent, then inside the Child component you can get props. ChildRef. this.childRef = el} /> and this represents the parent component. This callback is called when the Child component is mounted. We pass the DOM object of the input element as a parameter to the callback function, so that the parent component can directly manipulate the attributes of an HTML element inside the child component. A very clever use of function closures makes the connection between the two. You can’t do this with strings, so this is one of the reasons why strings are not recommended.
-
Ref to forward
const Child = React.forwardRef((props, ref) => { return <input ref={ref} defaultValue={props.defaultValue} /> } ) class MyComponent extends React.Component{ constructor(props) { super(props) this.childRef = React.createRef() } focus() { this.childRef.current.focus() } render () { return ( <div> <Child defaultValue={'ref'} ref={this.childRef}></Child> <button onClick={() => this.focus()}>focus</button> </div> ); }}Copy the code
The react.forwardref ()API is used to forward the ref attribute automatically to its child elements. React.forwardref () takes a function whose second argument receives the component’s ref property and can be passed down;