最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React ref的使用示例

 更新時間:2021年04月09日 09:16:59   作者:陳小瓦  
這篇文章主要介紹了React ref的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用React,感興趣的朋友可以了解下

寫了一段時間的 react,99%都在寫 state、prop、useState、useEffect,對 ref 特別不熟悉,前幾天做一個需求,想用 ref 實(shí)現(xiàn)父組件撈子組件的某個狀態(tài)值,結(jié)果失敗了,特此整理一下 ref 相關(guān)內(nèi)容。

什么是 ref

官網(wǎng)介紹:

在典型的 React 數(shù)據(jù)流中,props 是父組件與子組件交互的唯一方式。要修改一個子組件,你需要使用新的 props 來重新渲染它。但是,在某些情況下,你需要在典型數(shù)據(jù)流之外強(qiáng)制修改子組件。被修改的子組件可能是一個 React 組件的實(shí)例,也可能是一個 DOM 元素。對于這兩種情況,React 都提供了解決辦法,即使用 ref 來獲取 dom 或組件實(shí)例。

如何使用 ref

放在 dom 元素上

這是 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>
  }
}

打印看一下 ref 是啥

可以看出,ref.current 拿到了 dom 元素,所以我們可以實(shí)現(xiàn) dom 元素本身的一些功能,如 input 的聚焦:

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>
    )
  }
}

官網(wǎng)還提供了一種 ref 回調(diào)的形式:

export class Demo extends React.Component {
  constructor(props) {
    super(props)
    this.myRef = null
  }

  onClick = () => {
    this.myRef.focus()
  }

  render() {
    return (
      <div>
        <button onClick={this.onClick}>聚焦</button>
        <input ref={ele => this.myRef = ele} /> // 這里的 ele 就是該 dom 元素
      </div>
    )
  }
}

放在類組件上

其實(shí)組件跟原生 dom 差不多,也是擁有自己的 ui、一些功能的某種元素,所以將 ref 放在組件上,也可以獲取到該組件的示例。

// 子組件
class Child extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      name: 'xx'
    }
  }
  render() {
    return <div>子元素{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} />
    )
  }
}

那既然可以獲取到子組件的實(shí)例,我們就可以操作子組件了,比如文章最開始說,我想在父組件里去撈子組件的某些狀態(tài)值。

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}>點(diǎn)擊+1:{this.state.count}</button>
  }
}

export class Demo extends React.Component {
  constructor(props) {
    super(props)
    this.myRef = createRef()
  }

  onClick = () => {
    console.log(this.myRef.current.state.count) // 拿到子組件的狀態(tài)值
  }


  render() {
    return (
      <div>
        <button onClick={this.onClick}>獲取子組件的點(diǎn)擊次數(shù)</button>
        <Child ref={this.myRef} /> // ref 獲取到子組件實(shí)例
      </div>
    )
  }
}

既然能拿值,我也能拿函數(shù)去修改子組件

class Child extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      name: 'xx'
    }
  }
  changeName = () => {
    this.setState({name: 'ww'})
  }
  render() {
    return <div>子元素{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}>改變子組件的狀態(tài)</button>
        <Child ref={this.myRef} />
      </div>
    )
  }
}

當(dāng)然這個例子并不恰當(dāng),父組件想更改子組件的狀態(tài)的話,應(yīng)該把狀態(tài)提升到父組件中,然后作為子組件的props傳遞進(jìn)去。
主要是 ref 提供一種方式去繞過 props 來實(shí)現(xiàn)父子組件通信。

放在函數(shù)組件上

這是我文章開頭寫需求時犯的錯,ref 不能放在函數(shù)組件上,因為函數(shù)組件沒有實(shí)例。

const Child = () => {
  return <div>子組件</div>
}

export const Demo = () => {
  const myRef = useRef() // 可以在函數(shù)組件內(nèi)創(chuàng)建 ref

  useEffect(() => {
    console.log(myRef)
  }, [])

  return <Child ref={myRef} /> // 但是放在函數(shù)組件上無效
}

那函數(shù)組件就不能使用 ref 了嗎,那肯定不是哈哈。我們可以使用 forwardRef 包裝函數(shù)組件。

const Child = (props, ref) => { // 包裝后,除了原有的 props 外, ref 也被傳了進(jìn)來
  return <div ref={ref}>子組件</div> // 還是得掛載到 dom 上
}

const ProChild = React.forwardRef(Child) // 重點(diǎn)在這里

export const Demo = () => {
  const myRef = useRef()

  useEffect(() => {
    console.log(myRef)
  }, [])

  return <ProChild ref={myRef} />
}

這里貼一下官網(wǎng)的 tip:

那既然函數(shù)組件也可以使用 ref 的話,我們用函數(shù)組件實(shí)現(xiàn)一下父組件撈子組件的數(shù)據(jù),不過可以看出,使用 forwardRef 包裹后,ref 還是得掛載到 dom 或者類組件上,如果我只想掛載數(shù)據(jù)還需要搭配 useImperativeHandle。

const Child = (props, ref) => {
  const [count, setCount] = useState(0)

  useImperativeHandle(
    ref,
    () => ({   // 這里就是暴露給外部 ref 的數(shù)據(jù)
      getVal: ()=> count
    }),
    [count],
  )

  const onClick = () => {
    setCount(pre => pre+1)
  }
  return <button onClick={onClick}>點(diǎn)擊+1:{count}</button>
}

const ProChild = React.forwardRef(Child)

export const Demo = () => {
  const myRef = useRef()

  const onClick = () => {
    console.log(myRef.current.getVal()) // 拿到子組件的值
  }

  return <><button onClick={onClick}>獲取子組件的點(diǎn)擊次數(shù)</button><ProChild ref={myRef} /></>
}

至此完成了做需求時留下的問題 ✅

總結(jié)

最后還是需要強(qiáng)調(diào)一下,父組件獲取子組件狀態(tài)的場景,一般還是狀態(tài)提升 + 回調(diào)來通信,需求最終也是使用這種方式來實(shí)現(xiàn)的,最開始之所以想用 ref,是覺得狀態(tài)提升后,子組件變化了會引起父組件的重新渲染,但是我只想拿數(shù)據(jù)而不引起渲染。
跟師傅說了一下我寫需求時的想法,師傅見解如下:

  • 優(yōu)先考慮狀態(tài)提升
  • 有性能問題的話,考慮狀態(tài)提升 + memo
  • 不想給多個組件加 memo 的話,就要考慮引入 redux/mobx 了
  • 如果引入 redux/mobx 是一種成本的話,那 ref 也不是不可以哈哈哈

以上就是React ref的使用詳解的詳細(xì)內(nèi)容,更多關(guān)于React ref的使用的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在React 組件中使用Echarts的示例代碼

    在React 組件中使用Echarts的示例代碼

    本篇文章主要介紹了在React 組件中使用Echarts的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-11-11
  • 關(guān)于React Native 無法鏈接模擬器的問題

    關(guān)于React Native 無法鏈接模擬器的問題

    許多朋友遇到React Native 無法鏈接模擬器的問題,怎么解決呢,本文給大家分享完整簡便解決方法及配置例題,對React Native 鏈接模擬器相關(guān)知識感興趣的朋友一起看看吧
    2021-06-06
  • 詳解如何在React中優(yōu)雅的使用addEventListener

    詳解如何在React中優(yōu)雅的使用addEventListener

    這篇文章主要為大家詳細(xì)介紹了如何在React中優(yōu)雅的使用addEventListener,文中的示例代碼簡潔易懂,對大家學(xué)習(xí)React有一定的幫助,需要的可以參考一下
    2023-01-01
  • React中setState更新狀態(tài)的兩種寫法

    React中setState更新狀態(tài)的兩種寫法

    在?React?中,我們經(jīng)常需要更新組件的狀態(tài)(state),使用?setState?方法是一種常見的方式來實(shí)現(xiàn)狀態(tài)的更新,而在使用?setState?方法時,有兩種不同的寫法,即對象式和函數(shù)式,本文將介紹這兩種寫法的區(qū)別和使用場景,需要的朋友可以參考下
    2024-03-03
  • React中使用collections時key的重要性詳解

    React中使用collections時key的重要性詳解

    這篇文章主要給大家介紹了關(guān)于在React.js中使用collections時key的重要性,注意:一定不能不能忘了key,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-08-08
  • React?antd中setFieldsValu的簡便使用示例代碼

    React?antd中setFieldsValu的簡便使用示例代碼

    form.setFieldsValue是antd?Form組件中的一個方法,用于動態(tài)設(shè)置表單字段的值,它接受一個對象作為參數(shù),對象的鍵是表單字段的名稱,值是要設(shè)置的字段值,這篇文章主要介紹了React?antd中setFieldsValu的簡便使用,需要的朋友可以參考下
    2023-08-08
  • React腳手架搭建的學(xué)習(xí)

    React腳手架搭建的學(xué)習(xí)

    本文主要介紹了React腳手架搭建的學(xué)習(xí),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • React中如何引入Angular組件詳解

    React中如何引入Angular組件詳解

    這篇文章主要給大家介紹了關(guān)于React中如何引入Angular組件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08
  • 如何深入理解React的ref 屬性

    如何深入理解React的ref 屬性

    關(guān)于 Refs ,React 官網(wǎng)講解的對于新手來說不太友好,還是自己一字一句解讀后并以代碼驗證的方式后真正理解的.
    2021-05-05
  • React中的Hooks路由跳轉(zhuǎn)問題

    React中的Hooks路由跳轉(zhuǎn)問題

    這篇文章主要介紹了React中的Hooks路由跳轉(zhuǎn)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評論

葵青区| 大名县| 乌苏市| 阳信县| 柳江县| 黄龙县| 潞城市| 祁阳县| 奉新县| 庄浪县| 新安县| 宜兰县| 衢州市| 蓬安县| 安平县| 关岭| 和龙市| 台南市| 长岭县| 翁牛特旗| 德昌县| 吉木乃县| 静乐县| 乌兰察布市| 济宁市| 井陉县| 广河县| 巴塘县| 凤凰县| 巩义市| 保亭| 甘泉县| 揭西县| 上犹县| 新巴尔虎左旗| 台安县| 玛曲县| 宁安市| 蓬安县| 延边| 团风县|