[英]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 callbacks
在componentDidMount
或componentDidUpdate
生命周期挂钩之前被调用。仅使用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.