在react典型的数据流中,props
传递是父子组件交互的一种方式;通过传递一个新的props
值来使子组件重新render
,从而达到父子组件通信。某些情况下(例如和第三方的dom库整合,或者某个dom
元素focus等)为了修改子组件我们可能需要另一种方式,这就是ref
方式。
React提供的这个ref
属性,表示为对组件真正实例的引用,其实就是ReactDOM.render()
返回的组件实例;需要区分一下,ReactDOM.render()
渲染组件时返回的是组件实例;而渲染dom
元素时,返回是具体的dom节点。
1. react ref
state = {
inputVisible: false,
inputValue: '',
};
render() {
const { inputVisible, inputValue } = this.state;
return (
{inputVisible?(
<Input
ref={input=>{
this.input = input;
}}
value={inputValue}
onChange={e=>{
this.setState({ inputValue: e.target.value });
}}
/>
):(
<Tag
onClick={()=>{
this.setState({ inputVisible: true }, () => this.input.focus());}
}>
<PlusOutlined /> New Tag
</Tag>
)}
)
}
// 父组件
import { PureComponent } from 'react';
import Children from './Children';
export default class Parent extends PureComponent {
constructor() {
super();
this.state = {}
}
getChildren(){
console.log(this.childrenRef)
}
render(){
return (
<div>
<div onClick={()=>this.getChildren()}></div>
<Children onRef={(ref)=>(this.childrenRef = ref)}/>
</div>
);
}
}
// 子组件
import { PureComponent } from 'react';
export default class Children extends PureComponent {
constructor() {
super();
this.state = {name: 'Children'}
}
componentDidMount() {
this.props.onRef(this)
}
render(){
return (
<div>{this.state.name}</div>
);
}
}
https://www.cnblogs.com/wonyun/p/6395849.html
2. hook ref
import { useState, useEffect, useRef } from 'react';
const inputRef = useRef(null)
const [inputVisible,setInputVisible] = useState<boolean>(false);
const [inputValue,setInputValue] = useState<string>('');
useEffect(() => {
inputVisible && inputRef.current.focus()
},[inputVisible]);
return (
{inputVisible?(
<Input
ref={inputRef}
value={inputValue}
onChange={(e)=>setInputValue(e.target.value)}
/>
):(
<Tag onClick={()=>{setInputVisible(true);}}>
<PlusOutlined /> New Tag
</Tag>
)}
)
3. 比较
- react
// 定义ref ref={(ref) => { this.inputRef= ref }} // 使用ref this.inputRef.focus()
- react hook
// 声明ref const inputRef= useRef() // 复值给组件 ref={inputRef} // 使用ref inputRef.current.focus()
4. 问题解决
为什么useRef Hook的.current为空
Ref.current
为空,因为只有在函数返回并呈现内容之后才设置ref。每当传递给useffect钩子的数组的内容值发生更改时,它都会触发useffect钩子。通过在数组中传递 observed 并将记录 observed 的回调传递到控制台,可以利用useffect钩子来完成任务。
useEffect(() => {
console.log(inputRef.current);
}, [inputVisible]);
Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
export default connect(( {user,api} ) => ({
currentUser: user.currentUser , api
}), null, null, { forwardRef: true })(Children);