如何将refs分配给多个组件

时间:2017-11-01 12:59:24

标签: javascript reactjs

我正在使用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不起作用......我认为由于有多个按钮,我无法添加状态。

4 个答案:

答案 0 :(得分:4)

你应该使用ref callback而不是ref而且是的你需要多个refs,数组应该是好的

根据文件:

  

React支持可以附加到任何属性的特殊属性   零件。 ref属性采用callback函数,并且   安装组件后将立即执行callback   或未安装。

     

在HTML元素上使用ref属性时,ref callback   接收底层DOM元素作为其参数。

     在ref callbacks或之前调用

componentDidMount   componentDidUpdate生命周期钩子。

     

使用ref回调只是为了在类上设置属性是很常见的   用于访问DOM元素的模式。首选方法是设置   ref回调中的属性,如上例所示。甚至有   一种较短的写作方式:ref={input => this.textInput = input}.

字符串引用是遗留的,并且根据 docs

旧版API:字符串参考

  

如果您之前使用过React,那么您可能熟悉旧版本   其中ref属性是字符串的API,如“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>
    );
  }

答案 1 :(得分:2)

与@ ShubhamKhatri一样,使用// from: { friends: [1, 27, 42] } // to: { friends: [ { id: 1, name: 'Charlie' }, { id: 27, name: 'Parker' }, { id: 42, name: 'Brown' }, ] } 的答案是一种选择。您也可以通过状态实现所需的行为。

示例 (单一禁用按钮选项)

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

答案 2 :(得分:1)

对于功能组件(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} />)

答案 3 :(得分:0)

您可以使用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,您应该像在the answer by @bennygenel中那样通过React在<button>上的状态和props来完成它。但是,如果您需要做其他事情(在按钮上调用命令式DOM方法,读取不受控制的输入元素的值,读取元素的屏幕位置等),则需要使用这样的ref。 / p>