如何通过点击React组件外部的按钮触发组件刷新?
解决方案
你要实现这个需求有两种可行方案,优先推荐第一种符合React开发规范的方案:
方案1:将按钮纳入React组件内部(推荐)
这种方案遵循React单向数据流的设计逻辑,维护成本最低。你只需要把拉取随机名言的逻辑抽成公共方法,绑定给按钮点击事件即可,修改后的完整代码如下:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { quote: '' }; // 绑定this指向 this.fetchRandomQuote = this.fetchRandomQuote.bind(this); } // 把拉取逻辑抽成公共方法 fetchRandomQuote() { fetch("https://type.fit/api/quotes") .then(res => res.json()) .then((result) => { this.setState({ quote: result[Math.floor(Math.random() * result.length)] }); }) } componentDidMount() { // 组件挂载时首次拉取 this.fetchRandomQuote(); } render() { return ( <> <p id='reactQuote'>{this.state.quote.text}</p> <button id='new-quote' onClick={this.fetchRandomQuote}>New Quote</button> </> ); } } ReactDOM.render(<MyComponent />, document.getElementById('text'))
对应的HTML只需要保留挂载节点即可:
<div id="text"></div>
方案2:按钮保留在React组件外部
如果你的业务场景必须把按钮放在组件外部,可以把刷新方法挂载到全局window对象上,监听按钮点击触发即可,修改代码如下:
class MyComponent extends React.Component { constructor(props) { super(props); this.state = { quote: '' }; this.fetchRandomQuote = this.fetchRandomQuote.bind(this); } fetchRandomQuote() { fetch("https://type.fit/api/quotes") .then(res => res.json()) .then((result) => { this.setState({ quote: result[Math.floor(Math.random() * result.length)] }); }) } componentDidMount() { this.fetchRandomQuote(); // 把方法挂载到全局,供外部按钮调用 window.refreshQuote = this.fetchRandomQuote; // 绑定外部按钮点击事件 document.getElementById('new-quote').addEventListener('click', window.refreshQuote); } // 组件卸载时清除事件监听,避免内存泄漏 componentWillUnmount() { document.getElementById('new-quote').removeEventListener('click', window.refreshQuote); delete window.refreshQuote; } render() { return ( <p id='reactQuote'>{this.state.quote.text}</p> ); } } ReactDOM.render(<MyComponent />, document.getElementById('text'))
对应的HTML保留你原来的结构即可:
<div id="text"></div> <button id='new-quote'>New Quote</button>
额外优化提示
- 你当前的实现每次点击都会重新请求接口,你可以把首次拉取到的全量名言列表存在state里,后续随机选取的时候不需要重复请求,性能会更好
- 注意你原代码里
ReactDOM.render( MyComponent />缺少了左尖括号,实际运行需要补为<MyComponent />
内容的提问来源于stack exchange,提问作者Rey
相关产品推荐
相关产品推荐

