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

Higher-Order Components in ReactJS - extend functionalities from data components

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

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

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

让我用几行代码更好地解释一下。 下面的示例组件应该在用户单击事件上调用 API /favourites (POST) 以创建 "Favourite" 实体,并且它将调用相同的 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 有一个 属性 "create" 接受一个 JSON 负载,它会触发一个被 Saga 捕获的 Redux 动作(谁会调用 API )和它还能够通过 createListener 函数通知结果。 它对 delete prop 做同样的事情(但它会调用 delete API 并通过 favoriteDeleteHandler 通知)。

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

实际上,可以在不嵌套子组件的情况下使用 DataProviderApiFavourites,它 returns null 或 this.props.children if 已设置。

如果有人能帮助我理解我是否会做错事,我将不胜感激。

当然,HOC 非常适合这个用例。

代码很好,但是,为了坚持组合和可重用性的想法,我会构建一个更通用的 HOC,不要在其中放入那么多逻辑,然后如果您需要更具体的东西,传递参数或在其上构建另一个 HOC。

例如:

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

将存储作为参数传递给 HOC 的位置,然后如果需要它的特定片段,请将其指定为第一个参数或使用另一个 HOC 抽象。

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

  • 或者,recompose 也可以满足您的需求。
  • 同样,或者,你可以为 redux 的连接做一个 HOC,看看