I have been writing React for some time, 99% of which are writing state, prop, useState and useEffect. I am not familiar with ref. A few days ago, I made a requirement, trying to use REF to realize a state value of the parent component and its child component, but I failed.
What is the ref
In a typical React data flow, props is the only way for the parent component to interact with its children. To modify a child component, you need to re-render it using new props. However, in some cases, you need to force changes to subcomponents outside of the typical data flow. The child component being modified may be an instance of the React component or a DOM element. React provides a solution for both cases, which is to use the REF to get the DOM or component instance.
How to use ref
Put it on the DOM element
This is the most straightforward use of ref
export class Demo extends React.Component {
constructor(props) {
super(props)
this.myRef = createRef()
}
componentDidMount() {
console.log(this.myRef)
}
render() {
return <div ref={this.myRef}>测试</div>
}
}
Copy the code
Let’s print it and see what ref is
As you can see, ref.current gets the DOM element, so we can implement some of the dom elements themselves, such as input focus:
export class Demo extends React.Component { constructor(props) { super(props) this.myRef = createRef() } onClick = () => {this.myref.current. Focus ()} render() {return (<div> <button onClick={this.onclick}> </button> <input ref={this.myRef} /> </div> ) } }Copy the code
The official website also provides a form of ref callback:
export class Demo extends React.Component { constructor(props) { super(props) this.myRef = null } onClick = () => { This.myref.focus ()} render() {return (<div> <button onClick={this.onclick}> focus </button> <input ref={ele => this.myref = ele </div>)}}Copy the code
Put it on the class component
Just like the native DOM, a component is an element with its own UI and functionality, so you can get an example of that component by placing a REF on it.
Class Child extends React.Com {constructor(props) {super(props) this.state = {name: } render() {return <div> child {this.state.name}</div>}} export class Demo extends React.Component { constructor(props) { super(props) this.myRef = createRef() } componentDidMount() { console.log(this.myRef) } render() { return ( <Child ref={this.myRef} /> ) } }Copy the code
Now that we can get the instance of the child component, we can manipulate the child component. For example, I want to retrieve some state values of the child component from the parent component.
class Child extends React.Component { constructor(props) { super(props) this.state = { count: 0 } } onClick = () => { this.setState({count: This.state.count +1})} render() {return <button onClick={this.onclick}> {this.state.count}</button> } } export class Demo extends React.Component { constructor(props) { super(props) this.myRef = createRef onClick = = > () ()} {the console. The log (this) myRef). The current state. The count) / / to get the child components status value} render () {return (< div > <button onClick={this.onClick}> </button> <Child ref={this.myRef} /> // ref </div>)}}Copy the code
If I can get values, I can also get functions to modify child components
class Child extends React.Component { constructor(props) { super(props) this.state = { name: 'xx' } } changeName = () => { this.setState({name: 'ww')} render() {return <div> child {this.state.name}</div>}} export class Demo extends React.Component { constructor(props) { super(props) this.myRef = createRef() } onClick = () => { this.myRef.current.changeName() // Render () {return (<div> <button onClick={this.onclick}> </button> <Child ref={this.myref} /> </div> ) } }Copy the code
If the parent component wants to change the state of the child component, it should promote the state to the parent component and pass it as props for the child component. The ref provides a way to bypass props for parent-child component communication.
Put it on the function component
This is a mistake I made at the beginning of the article when I wrote requirements. Refs cannot be placed on function components because function components have no instances.
Const Child = () => {return <div> Child component </div>} export const Demo = () => {const myRef = useRef() // A ref can be created within a function component UseEffect (() => {console.log(myRef)}, []) return <Child ref={myRef} /> /Copy the code
Function components can not use ref, that is definitely not haha. We can wrap the function component with the forwardRef.
Const Child = (props, ref) => {// Return <div ref={ref}> Child </div> const ProChild = react.forwardref (Child const Demo = () => { const myRef = useRef() useEffect(() => { console.log(myRef) }, []) return <ProChild ref={myRef} /> }Copy the code
Here’s the tip from the official website:
The parent component can also use the parent component to retrieve the parent component’s data. The parent component can also use the parent component to retrieve the parent component’s data. If I only want to mount data, I also need to useImperativeHandle.
const Child = (props, ref) => { const [count, setCount] = useState(0) useImperativeHandle( ref, () => ({// here is the data exposed to the external ref: ()=> count}), [count],) const onClick= ()=> {setCount(pre => pre+1)} return <button onClick={onClick}> {count}</button> } const ProChild = React.forwardRef(Child) export const Demo = () => { const myRef = useRef() const OnClick = () => {console.log(myref.current.getVal ())} return <><button </button><ProChild ref={myRef} /></>}Copy the code
This completes the problem left when doing requirements ✅
conclusion
Finally still need to emphasize that the parent component to get the state of the subcomponents, general state or improve communication + callbacks, also use this way to implement demand finally, the most I want to start in ref, ascension is thought form, child components change causes the parent component to apply colours to a drawing, but I just want to get the data without causing rendering. I told my master what I thought when I wrote requirements. His opinion is as follows:
- Prioritize status improvement
- If there are performance issues, consider state promotion + Memo
- If you don’t want to add memos to multiple components, consider redux/ MOBx
- If introducing redux/ MOBx is a cost then ref is not out of the question hahaha