在使用 Redux、React 和 react-router 时从动态组件获取 ref-dom 4.x
Getting the ref from a dynamic component when using Redux, React and react-router-dom 4.x
我有以下class
class MatchBox extends React.Component {
constructor(props) {
super(props);
this.countdownHandler = null;
this.showBlocker = true;
this.start = this.start.bind(this);
}
start() {
...
}
render() {
...
return (
<div style={ styles.mainContainer } className="fluid-container">
...
</div>
);
}
};
function mapStateToProps(state) {
...
}
function matchDispatchToProps(dispatch) {
...
}
export default withRouter(connect(mapStateToProps, matchDispatchToProps, null, { withRef: true })(MatchBox));
在这个class
中使用
class GameBox extends React.Component {
constructor(props) {
super(props);
...
}
render() {
var mainElement = null;
switch(this.props.mainElement.element) {
case 'SEARCHING': mainElement = <SearchingBox gameType={ this.props.gameType }/>; break;
case 'MATCH': mainElement = <MatchBox ref='matchBox'/>; break;
default: mainElement = <SearchingBox/>;
}
return (
<div style={ styles.mainContainer } className="fluid-container">
{ mainElement }
</div>
);
}
};
function mapStateToProps(state) {
...
}
function matchDispatchToProps(dispatch) {
...
}
export default withRouter(connect(mapStateToProps, matchDispatchToProps, null, { withRef: true })(GameBox));
而且我无法获取对象 MatchBox 的引用。我尝试使用 this.refs.matchBox
并且为空,也尝试直接从 ref(ref={(r) => { // r is null } }
) 获取,但我不知道该尝试什么了。
我正在使用 react-router-dom 4,我不知道函数 withRouter
是否影响结果组件。
这不是很好,但我认为这是解决方案。 withRouter
通过 wrappedComponentRef
回调公开子引用,这让我们进入 connect
hoc。如果您像您一样传递 withRef
属性,则通过 getWrappedInstance
公开其子引用。所以你只需要将两者结合起来。
class GameBox extends React.Component {
matchboxRefCallback = (connectHOC) => {
this.matchboxRef = connectHOC ? connectHOC.getWrappedInstance() : null;
}
render() {
return <MatchBox wrappedComponentRef={this.matchboxRefCallback}/>;
}
}
更简洁的解决方案是创建一个 HOC。这会将引用转发给实际组件
const matchBoxHOC = (WrappedComponent) => {
class MatchBoxHOC extends React.Component {
render() {
const { forwardRef, ...rest } = this.props;
return <WrappedComponent {...rest} ref={forwardRef} />;
}
}
const WithRouterMatchBoxHOC = withRouter(MatchBoxHOC, { withRef: true });
return React.forwardRef((props, ref) => {
return <WithRouterMatchBoxHOC {...props} forwardRef={ref} />;
});
}
来电就好
export default matchBoxHOC(connect(mapStateToProps, matchDispatchToProps, null, { withRef: true })(MatchBox));
我有以下class
class MatchBox extends React.Component {
constructor(props) {
super(props);
this.countdownHandler = null;
this.showBlocker = true;
this.start = this.start.bind(this);
}
start() {
...
}
render() {
...
return (
<div style={ styles.mainContainer } className="fluid-container">
...
</div>
);
}
};
function mapStateToProps(state) {
...
}
function matchDispatchToProps(dispatch) {
...
}
export default withRouter(connect(mapStateToProps, matchDispatchToProps, null, { withRef: true })(MatchBox));
在这个class
中使用class GameBox extends React.Component {
constructor(props) {
super(props);
...
}
render() {
var mainElement = null;
switch(this.props.mainElement.element) {
case 'SEARCHING': mainElement = <SearchingBox gameType={ this.props.gameType }/>; break;
case 'MATCH': mainElement = <MatchBox ref='matchBox'/>; break;
default: mainElement = <SearchingBox/>;
}
return (
<div style={ styles.mainContainer } className="fluid-container">
{ mainElement }
</div>
);
}
};
function mapStateToProps(state) {
...
}
function matchDispatchToProps(dispatch) {
...
}
export default withRouter(connect(mapStateToProps, matchDispatchToProps, null, { withRef: true })(GameBox));
而且我无法获取对象 MatchBox 的引用。我尝试使用 this.refs.matchBox
并且为空,也尝试直接从 ref(ref={(r) => { // r is null } }
) 获取,但我不知道该尝试什么了。
我正在使用 react-router-dom 4,我不知道函数 withRouter
是否影响结果组件。
这不是很好,但我认为这是解决方案。 withRouter
通过 wrappedComponentRef
回调公开子引用,这让我们进入 connect
hoc。如果您像您一样传递 withRef
属性,则通过 getWrappedInstance
公开其子引用。所以你只需要将两者结合起来。
class GameBox extends React.Component {
matchboxRefCallback = (connectHOC) => {
this.matchboxRef = connectHOC ? connectHOC.getWrappedInstance() : null;
}
render() {
return <MatchBox wrappedComponentRef={this.matchboxRefCallback}/>;
}
}
更简洁的解决方案是创建一个 HOC。这会将引用转发给实际组件
const matchBoxHOC = (WrappedComponent) => {
class MatchBoxHOC extends React.Component {
render() {
const { forwardRef, ...rest } = this.props;
return <WrappedComponent {...rest} ref={forwardRef} />;
}
}
const WithRouterMatchBoxHOC = withRouter(MatchBoxHOC, { withRef: true });
return React.forwardRef((props, ref) => {
return <WithRouterMatchBoxHOC {...props} forwardRef={ref} />;
});
}
来电就好
export default matchBoxHOC(connect(mapStateToProps, matchDispatchToProps, null, { withRef: true })(MatchBox));