ReactJS中的高阶组件 - 扩展数据组件的功能

时间:2017-10-02 12:01:18

标签: reactjs react-redux redux-saga higher-order-components

我很抱歉这个愚蠢的问题,我正在学习React,所以我根本不是专家。

我想知道是否有一种方法可以扩展我的无状态组件的某些功能,而不会总是创建包装器,它们将连接到Redux存储并通过props传递数据。

高阶组件是最好的方法吗?

让我用几行代码更好地解释一下。 下面的示例组件应该在用户单击事件上调用API /收藏夹(POST)以创建“收藏夹”实体,并且它将调用相同的API(DELETE)以便将其删除。

这是我意识到的解决方案:

const HOC_DISPLAY_NAME = 'HOCFavouriteIcon';
export default function HOCWrapperFavourite(FavouriteComponent) {

return class extends React.Component {

    static displayName = HOC_DISPLAY_NAME;

    constructor(props) {
        super(props);
        this.state = this.getDefaultState();
        this.bindMethods();
    }

    getDefaultState() {
        return {
            isFavourite: false,
            addFavouritePayload: null,
            removeFavouritePayload: null,
        };
    }

    render() {
        return (
            <DataProviderApiFavourites
                create={this.state.addFavouritePayload}
                createListener={this.favoriteCreateHandler}
                delete={this.state.removeFavouritePayload}
                deleteListener={this.favoriteDeleteHandler}
            >
                <FavouriteComponent
                    {...this.props}
                    {...this.state}
                    addFavourite={this.addFavouriteClickHandler}
                    removeFavourite={this.removeFavouriteClickHandler}
                />
            </DataProviderApiFavourites>

        );
    }

    addFavouriteClickHandler(visitorId, artId) {
            this.setState({
                addFavouritePayload: {visitorId, artId},
            });
    }

    removeFavouriteClickHandler(visitorId, favouriteId) {
            this.setState({
                removeFavouritePayload: {visitorId, favouriteId},
            });
    }

    favoriteCreateHandler(result){
        // do something when a favorite entity was created
    }

    favoriteDeleteHandler(result){
        // do something when a favorite entity was deleted
    }

    bindMethods() {
        this.addFavouriteClickHandler = this.addFavouriteClickHandler.bind(this);
        this.removeFavouriteClickHandler = this.removeFavouriteClickHandler.bind(this);
        this.favoriteCreateHandler = this.favoriteCreateHandler.bind(this);
        this.favoriteDeleteHandler = this.favoriteDeleteHandler.bind(this);
    }

}

};

DataProviderApiFavourites有一个接受JSON有效负载的属性“create”,它将触发Saga捕获的Redux动作(谁将调用API),并且它还能够通过createListener函数通知结果。 删除支柱也是如此(但它会调用delete API并通过favoriteDeleteHandler进行通知)。

考虑到FavouriteComponent是一个无状态组件,为了使用UI组件中数据组件的功能,它是一个很好的结构吗?

实际上,可以在不嵌套子组件的情况下使用DataProviderApiFavourites,它返回null或者如果设置了this.props.children。

如果有人帮我理解我是否会做错事,我真的很感激。

1 个答案:

答案 0 :(得分:1)

当然,HOC完全适合此用例。

代码很好,但是要坚持组合和可重用性的概念,我将构建一个更通用的HOC,并且不要在其中添加太多逻辑,然后如果您需要更具体的内容,请传递参数或在其之上构建另一个HOC。

例如:

const HOC = store => WrappedComponent => props => (
    // Render your wrapped component, spread the store to his props
);

要将商店作为参数传递给HOC的地方,然后,如果需要其中的特定切片,可以将其指定为第一个参数,或者使用另一个HOC抽象。

简而言之,不要使用将直接接受包装的组件的HOC,而是将另一个HOC接受第一个参数,这将为您提供更大的灵活性。第一个参数可以是redux存储,解构的redux存储,默认状态等,具体取决于您选择使用的逻辑。