假设我有一个如下的组件树
<App>
</Header>
<Content>
<SelectableGroup>
...items
</SelectableGroup>
</Content>
<Footer />
</App>
SelectableGroup
可以通过鼠标选择/取消选择它包含的项目。我正在将当前选择(选定项的数组)存储在redux存储中,以便App中的所有组件都可以读取它。
Content
组件已将ref
设置为SelectableGroup
,这使我能够以编程方式清除选择(调用clearSelection()
)。像这样:
class Content extends React.Component {
constructor(props) {
super(props);
this.selectableGroupRef = React.createRef();
}
clearSelection() {
this.selectableGroupRef.current.clearSelection();
}
render() {
return (
<SelectableGroup ref={this.selectableGroupRef}>
{items}
</SelectableGroup>
);
}
...
}
function mapStateToProps(state) {
...
}
function mapDispatchToProps(dispatch) {
...
}
export default connect(mapStateToProps, mapDispatchToProps)(Content);
我可以轻松地想象将这clearSelection()
传递给Content
的孩子们。但是,这又是我的问题,我可以从同级组件clearSelection()
调用Footer
吗?
Footer
派发一个动作,并向Redux商店设置某种“请求调用清除选择”状态吗?在componentDidUpdate()
的{{1}}回调中对此做出反应,然后立即调度另一个操作来重置此“请求清除选择的请求”状态?答案 0 :(得分:0)
您可以像这样使用ref来访问Content组件的全部功能
const { Component } = React;
const { render } = ReactDOM;
class App extends Component {
render() {
return (
<div>
<Content ref={instance => { this.content = instance; }} />
<Footer clear={() => this.content.clearSelection() } />
</div>
);
}
}
class Content extends Component {
clearSelection = () => {
alert('cleared!');
}
render() {
return (
<h1>Content</h1>
);
}
}
class Footer extends Component {
render() {
return (
<div>Footer <button onClick={() => this.props.clear()}>Clear</button>
</div>
);
}
}
render(
<App />,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>
答案 1 :(得分:0)
我认为上下文API在这种情况下会派上用场。在使用全局状态/ redux似乎不正确的情况下,或者当您将道具向下传递到组件树中的多个级别时,我开始大量使用它。
工作示例:
import React, { Component } from 'react'
export const Context = React.createContext()
//***************************//
class Main extends Component {
callback(fn) {
fn()
}
render() {
return (
<div>
<Context.Provider value={{ callback: this.callback }}>
<Content/>
<Footer/>
</Context.Provider>
</div>
);
}
}
export default Main
//***************************//
class Content extends Component {
render() {
return (
<Context.Consumer>
{(value) => (
<div onClick={() => value.callback(() => console.log('Triggered from content'))}>Content: Click Me</div>
)}
</Context.Consumer>
)
}
}
//***************************//
class Footer extends Component {
render() {
return (
<Context.Consumer>
{(value) => (
<div onClick={() => value.callback(() => console.log('Triggered from footer'))}>Footer: Click Me</div>
)}
</Context.Consumer>
)
}
}
//***************************//
假设内容和页脚以及其中的文件(content.js / footer.js)记住要从main.js导入Context