渲染后修改 React Child 组件道具
Modify React Child Component props after render
这是一个简单的例子:
copyButton = <SomeReactComponent title="My Button" />
this.clipboard = new Clipboard('button#copy-button');
this.clipboard.on('success', () => {
this.copyButton.props.title = "Copied!";
});
render = () => {
return (
...
{ this.copyButton }
...
);
}
使用 Clipboard.js,当我按下按钮时,我将一些文本复制到剪贴板。在成功复制时,我想更改复制按钮的标题以反映这一点。我一直引用的按钮组件已经呈现,this.copyButton.props.title
显然不起作用,因为组件是不可变的。
那么,我要如何更改按钮上 title
的值?我知道我可以在 parent 组件中有一个状态 属性 但我宁愿避免这种情况以使我的 parent 组件完全无状态。我可以简单地在成功回调中重新分配 this.copyButton
吗(我试过了,但运气不好)?
更一般地说,parent 组件应该如何更新它们的 children 属性(如果有的话)?使用状态真的是唯一的方法吗?
注意:如果重要的话,我使用的是 ES6。
考虑到您正在尝试更新按钮文本的状态,而不以某种形式(在父组件或子组件中)使用反应状态可能会让人觉得有点笨拙。然而,这是可能的。想到的最初方法是使用 React.cloneElement
创建一个新版本的 copyButton
和你想要的 title
道具。然后使用 this.forceUpdate
重新渲染带有更新子组件的父组件。像这样:
this.clipboard.on('success', () => {
this.copyButton = React.cloneElement(this.copyButton, {
title: 'Copied!'
});
this.forceUpdate();
});
https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement
也就是说,在这种情况下使用 state
对于可读性和运行时来说几乎肯定会更好(克隆元素和强制 re-render 并不便宜)。
我觉得这不是很 Reacty。
我想你想做这样的事情:
getInitialState = () => {
return {
title: 'Button Title'
};
};
componentDidMount = () => {
this.clipboard = new Clipboard(this.refs.copyButton);
this.clipboard.on('success', () => {
this.setState({
title: 'Copied!'
})
});
};
componentWillUnmount = () => {
// You should destroy your clipboard and remove the listener
// when the component unmounts to prevent memory leaks
this.clipboard.destroy();
// or whatever the comparable method is for clipboard.js
};
render = () => {
return (
...
<SomeReactComponent ref="copyButton" title={this.state.title} />
...
);
};
最终结果是您的按钮安装在初始渲染上。然后它的 ref 被传递到 componentDidMount()
中,它会实例化您的剪贴板和 success
侦听器。单击按钮时,它会调用 this.setState()
来更新按钮组件的内部 title
状态,这会自动触发具有新标题的组件 re-render。
此外,根据 React docs,如果可以的话,您想尽量避免使用 forceUpdate()
。
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient.
这是一个简单的例子:
copyButton = <SomeReactComponent title="My Button" />
this.clipboard = new Clipboard('button#copy-button');
this.clipboard.on('success', () => {
this.copyButton.props.title = "Copied!";
});
render = () => {
return (
...
{ this.copyButton }
...
);
}
使用 Clipboard.js,当我按下按钮时,我将一些文本复制到剪贴板。在成功复制时,我想更改复制按钮的标题以反映这一点。我一直引用的按钮组件已经呈现,this.copyButton.props.title
显然不起作用,因为组件是不可变的。
那么,我要如何更改按钮上 title
的值?我知道我可以在 parent 组件中有一个状态 属性 但我宁愿避免这种情况以使我的 parent 组件完全无状态。我可以简单地在成功回调中重新分配 this.copyButton
吗(我试过了,但运气不好)?
更一般地说,parent 组件应该如何更新它们的 children 属性(如果有的话)?使用状态真的是唯一的方法吗?
注意:如果重要的话,我使用的是 ES6。
考虑到您正在尝试更新按钮文本的状态,而不以某种形式(在父组件或子组件中)使用反应状态可能会让人觉得有点笨拙。然而,这是可能的。想到的最初方法是使用 React.cloneElement
创建一个新版本的 copyButton
和你想要的 title
道具。然后使用 this.forceUpdate
重新渲染带有更新子组件的父组件。像这样:
this.clipboard.on('success', () => {
this.copyButton = React.cloneElement(this.copyButton, {
title: 'Copied!'
});
this.forceUpdate();
});
https://facebook.github.io/react/docs/top-level-api.html#react.cloneelement
也就是说,在这种情况下使用 state
对于可读性和运行时来说几乎肯定会更好(克隆元素和强制 re-render 并不便宜)。
我觉得这不是很 Reacty。
我想你想做这样的事情:
getInitialState = () => {
return {
title: 'Button Title'
};
};
componentDidMount = () => {
this.clipboard = new Clipboard(this.refs.copyButton);
this.clipboard.on('success', () => {
this.setState({
title: 'Copied!'
})
});
};
componentWillUnmount = () => {
// You should destroy your clipboard and remove the listener
// when the component unmounts to prevent memory leaks
this.clipboard.destroy();
// or whatever the comparable method is for clipboard.js
};
render = () => {
return (
...
<SomeReactComponent ref="copyButton" title={this.state.title} />
...
);
};
最终结果是您的按钮安装在初始渲染上。然后它的 ref 被传递到 componentDidMount()
中,它会实例化您的剪贴板和 success
侦听器。单击按钮时,它会调用 this.setState()
来更新按钮组件的内部 title
状态,这会自动触发具有新标题的组件 re-render。
此外,根据 React docs,如果可以的话,您想尽量避免使用 forceUpdate()
。
Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). This makes your component "pure" and your application much simpler and more efficient.