繁体   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