【问题标题】:React composition: expose higher-order methodsReact 组合:暴露高阶方法
【发布时间】:2017-01-12 13:28:46
【问题描述】:

由于我看到 React 团队不鼓励开发人员使用继承,我正在尝试使用组合来代替。

export class Page extends React.PureComponent {

    shouldComponentUpdate(nextProps, nextState) {
        return !isEqual(nextProps, this.props) || !isEqual(nextState, this.state);
    }

    render() {
        return this.props.children;
    }
}


const mapStateToProps = (state, ownProps) => {
    return {}
};

const mapDispatchToProps = (dispatch) => {
    return {
        onNextClick: () => dispatch(customAction())
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(Page);


export class FirstPage extends React.PureComponent {

    render() {
        return (
            <Page>
                <div>
                    <h1>Title</h1>
                    <Button onClick={this.props.onNextClick}>Next</Button>
                </div>
            </Page>
        );
    }
}

const mapStateToProps = (state, ownProps) => {
    return {}
};

const mapDispatchToProps = (dispatch) => {
    return {
        onNextClick: () => dispatch(customAction())
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(FirstPage);

在这种情况下,几个组件将使用 Page 作为容器,并且会有一个下一步按钮。我想为页面组件中的下一个按钮单击公开一个通用处理程序,以避免重复dispatch(customAction())。 我可以通过继承轻松实现这一点,但我坚持使用组合模式。 有什么想法吗?

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    我建议你为Page children 提供额外的道具:

    export class Page extends React.PureComponent {
    
        shouldComponentUpdate(nextProps, nextState) {
            return !isEqual(nextProps, this.props) || !isEqual(nextState, this.state);
        }
    
        render() {
            const {onNextClick} = this.props;
            return React.cloneElement(this.props.children, {onNextClick});
        }
    }
    
    const mapDispatchToProps = (dispatch) => {
        return {
            onNextClick: () => dispatch(customAction())
        }
    };
    
    export default connect(null, mapDispatchToProps)(Page);
    
    
    export class FirstPage extends React.PureComponent {
        render() {
            return (
                <div>
                    <h1>Title</h1>
                    <Button onClick={this.props.onNextClick}>Next</Button>
                </div>
            );
        }
    }
    
    export class App extends React.PureComponent {
        render() {
            return (
                <Page>
                    <FirstPage />
                </Page>
            );
        }
    }
    

    【讨论】:

    • 这太明显了!谢谢。
    【解决方案2】:

    您可以使用ref 来引用Page 元素。

    class Page extends React.Component {
      nextHandler(){
        console.log("I am in the parent.");
      }
      
      render(){
        return this.props.children;
      }
    }
    
    class FirstPage extends React.Component {
      render(){
        return (
          <Page ref={ page => this.page = page }>
            <div>
              <h1>Title</h1>
              <button onClick={ () => this.page.nextHandler() }>Next</button>
            </div>
          </Page>
        )
      }
    }
    
    ReactDOM.render(<FirstPage />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>

    【讨论】:

    • 这是一种方法,但我觉得它不是很优雅。还是谢谢你。
    猜你喜欢
    • 2018-09-17
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-25
    相关资源
    最近更新 更多