簡體   English   中英

如何將引用分配給多個組件

[英]How to assign refs to multiple components

我正在使用React使用array.map渲染多個數據。
如何禁用列表中的單擊按鈕?

這是我的代碼:

  onRunClick(act, e) {
    this.refs.btn.setAttribute("disabled", true);
  }

  render () {
    return (
      <div>
        {
          this.state.acts.map((act) => {
            let boundActRunClick = this.onRunClick.bind(this, act);

            return (
              <p key={act._id}>
                Name: {act.name}, URL(s): {act.urls}
                <button ref='btn' onClick={boundActRunClick}>Run</button>
              </p>
            )
          })
        }
      </div>
    );
  }
}

使用refs無效...我認為我無法添加狀態,因為有多個按鈕。

您應該使用ref callback而不是ref,而且是的,您需要多個ref,一個數組應該很好

根據文檔:

React支持一個可以附加到任何組件的特殊屬性。 ref屬性具有callback函數,在掛載或卸載組件之后,將立即執行該callback

在HTML元素上使用ref屬性時, ref callback接收基礎DOM元素作為其參數。

ref callbackscomponentDidMountcomponentDidUpdate生命周期掛鈎之前被調用。

僅使用ref回調在類上設置屬性是訪問DOM元素的常見模式。 首選方法是像上面的示例一樣在ref回調中設置屬性。 甚至還有一種更短的編寫方法: ref={input => this.textInput = input}.

字符串引用是舊版,並且根據docs

舊版API:字符串引用

如果您之前使用過React,那么您可能會熟悉一個較舊的API,其中ref屬性是一個字符串,例如“ textInput”,並且DOM節點可以通過this.refs.textInput訪問。 我們建議不要這樣做,因為字符串引用存在一些問題,被認為是舊問題,並且很可能在將來的發行版中刪除。 如果您當前正在使用this.refs.textInput訪問refs ,則建議改用回調模式。

constructor() {
    super();
    this.btn = [];
}
onRunClick(act, index, e) {
    this.btn[index].setAttribute("disabled", true);
  }

  render () {
    return (
      <div>
        {
          this.state.acts.map((act, index) => {
            let boundActRunClick = this.onRunClick.bind(this, act, index);

            return (
              <p key={act._id}>
                Name: {act.name}, URL(s): {act.urls}
                <button ref={(ref) => this.btn[index] = ref} onClick={boundActRunClick}>Run</button>
              </p>
            )
          })
        }
      </div>
    );
  }

像@ShubhamKhatri的使用ref的答案是一個選項。 您也可以通過狀態來實現所需的行為。

示例 (單個禁用按鈕選項)

class App extends Component{
  constructor() {
    super();
    this.state = {
      disabled: ''
    };
  }

  onRunClick(act, index, e) {
    this.setState({ disabled: act._id });
  }

  render() {
    return (
      <div>
        {
          this.state.acts.map((act, index) => {
            let boundActRunClick = this.onRunClick.bind(this, act, index);
            return (
              <p key={act._id}>
                Name: {act.name}, URL(s): {act.urls}
                <button disabled={this.state.disabled === act._id} onClick={boundActRunClick}>Run</button>
              </p>
            )
          })
        }
      </div>
    );
  }
}

示例 (多個禁用按鈕選項)

class App extends Component{
  constructor() {
    super();
    this.state = {
      buttons: {}
    };
  }

  onRunClick(act, index, e) {
    this.setState((prevState) => { 
      const buttons = Object.assign({}, prevState.buttons, { [act._id]: !prevState.buttons[act._id] });
      return { buttons };
    });
  }

  render() {
    return (
      <div>
        {
          this.state.acts.map((act, index) => {
            let boundActRunClick = this.onRunClick.bind(this, act, index);
            return (
              <p key={act._id}>
                Name: {act.name}, URL(s): {act.urls}
                <button disabled={this.state.buttons[act._id] || false} onClick={boundActRunClick}>Run</button>
              </p>
            )
          })
        }
      </div>
    );
  }
}

您可以使用npm模塊react-multi-ref (我的一個小庫)來執行此操作。

import React from 'react';
import MultiRef from 'react-multi-ref';

class Foo extends React.Component {
  _actRefs = new MultiRef();

  onRunClick(act, e) {
    this._actRefs.map.get(act._id).setAttribute("disabled", true);
  }

  render () {
    return (
      <div>
        {
          this.state.acts.map((act) => {
            let boundActRunClick = this.onRunClick.bind(this, act);

            return (
              <p key={act._id}>
                Name: {act.name}, URL(s): {act.urls}
                <button ref={this._actRefs.ref(act._id)} onClick={boundActRunClick}>Run</button>
              </p>
            )
          })
        }
      </div>
    );
  }
}

盡管在這種特定情況下,您只想更改元素的屬性,而不是使用ref,您應該通過React通過<button>上的state和props來實現它,就像@bennygenel的回答一樣 但是,如果您需要做其他事情(在按鈕上調用命令式DOM方法,讀取不受控制的輸入元素的值,讀取元素的屏幕位置等),則需要使用這樣的ref。

對於功能組件(React 16+),您可以按以下方式進行處理:

/* 
 * @param {Object|Function} forwardedRef callback ref function  or ref object that `refToAssign` will be assigned to
 * @param {Object} refToAssign React ref object
 */
export function assignForwardedRefs(forwardedRef, refToAssign) {
  if (forwardedRef) {
    if (typeof forwardedRef === 'function') {
      forwardedRef(refToAssign)
    } else {
      forwardedRef.current = refToAssign
    }
  }
}


function MyComponent({
  forwardedRef
}) {
   const innerRef = useRef()

   function setRef(ref) {
     assignForwardedRefs(forwardedRef, ref)
     innerRef.current = ref
   }

   return <div ref={setRef}>Hello World!</div>
}

export default React.forwardRef((props, ref) => <MyComponent {...props} forwardedRef={ref} />)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM