javascript - ReactJs - 可重用的 Redux 服务

标签 javascript reactjs redux

我了解 Redux 的操作、缩减器和存储映射的概念。 我已经能够在我的应用程序中成功执行 Redux。

我愉快地使用 React 的 contextTypes 为需要来自之前调用的 Redux 的数据的子组件。

然后我遇到了一个奇怪的情况,数据被一个 child 变异了。当我在 SO 上发布问题时,一位成员告诉我无论如何我应该谨慎使用 contextTypes。

因此,解决我的问题的唯一方法是映射到存储,AGAIN,在 child 的父级中,就像父级的更高组件之前所做的那样,并将该数据作为 Prop 传递给 child .

但这对我来说似乎都是错误的。再次映射到同一家商店?为什么?我不明白什么?为什么我必须在每个需要映射到另一个组件的相同数据的组件上写这个?

  export default class Foo extends Component {        

  .....

  // I DID THIS STUFF IN A HIGHER COMPONENT.
  // WHY MUST I REPEAT MYSELF AGAIN?
  // WHAT AM I NOT UNDERSTANDING?

  static propTypes = {
    children: PropTypes.node.isRequired,
    dispatch: PropTypes.func.isRequired,
    products: PropTypes.array
  };

  componentDidMount() {
    const { dispatch } = this.props;  
    dispatch(fetchProductsIfNeeded());
  }

  .....

 }  

const mapStateToProps = (state) => {
  const {productsReducer } = state;
  if (!productsReducer) {
    return {
      isFetching: false,
      didInvalidate: false,
      error: null,
      products: []
    };
  }

  return {
    error: productsReducer.error,
    isFetching: productsReducer.isFetching,
    didInvalidate: productsReducer.didInvalidate,
    products: productsReducer.products
  };
};

export default connect(mapStateToProps)(Foo);

我查看了容器,但在我看来,容器会同时将所有dumb组件包装在其中......

   <ProductsContainer>
      <ProductsComponent />
      <ProductSpecialsComponent />
      <ProductsDiscountedComponent />
   </ProductsContainer>

这不是我想要的。我想,就像服务一样,我可以在每个相应的dumb组件中使用该容器......

   <ProductsContainer>
      <ProductsDiscountedComponent />
   </ProductsContainer>

   <ProductsContainer>
      <ProductSpecialsComponent />
   </ProductsContainer>

   <ProductsContainer>
      <ProductsComponent />
   </ProductsContainer>

现在,为了获得上面说明的 3 个子组件,它们中的每一个都必须映射到商店,这似乎都是错误的。

我找不到任何我可以掌握的解决方案。

问题:

有没有一种方法可以一次映射到特定商店,并为那些需要该数据的组件调用该“服务”?

如果是这样,将不胜感激。

后脚本:

我虽然也许如果我可以将“映射服务”作为一个纯粹的 JavaScript 函数 o/s 来执行,并且只在需要它的组件中导入该函数,那将解决问题,但我还没有看到任何Redux 商店映射到 o/s React 的示例。

更新:

我把解决方案贴在这里......

React-Redux - Reuseable Container/Connector

最佳答案

首先,谈谈你过去的问题。的确,上下文不适合这样的事情。您还应该担心您提到的突变。如果您使用的是 Redux 存储,则退出它的数据应该始终是不可变的。也许像 Immutable.js 这样的图书馆会在那里提供帮助。


现在让我们来谈谈手头的事情。也许您没有完全理解什么是“哑”组件。dumb组件应该是无状态的并且是纯的:

const Product = ({ name, comments }) => (
  <div>
    <h1>{name}</h1>
    <CommentsList comments={comments} />
  </div>
);

组件从 props 获取它需要的一切。现在有很多方法可以将数据获取到这个组件中,但它们都是基于 props 的。例如,以下是最直接的:

const ProductList = ({ products }) => (
  <div>
    {products.map( p => <Product product={product} /> )}
  </div>
);

class App extends Component {
  getInitialState () {
    return { products: [] };
  }

  componentDidMount () {
    // connect to store, blah blah...
  }

  render () {
    return (
      <div>
        {/* blah blah */}
        <ProductsList products={this.state.products} />
        {/* blah blah */}
      </div>
    );
  }
}

正如您从示例中看到的那样,整个组件树将从 props 获取其状态,这些 props 从一个连接简单地传递到商店。除了 App 之外,所有组件都是哑的、无状态的和可预测的。

但也有一些情况,通过 Prop 连接整棵树是不切实际的,我们需要本地化连接到我们的商店。这就是 HOC 可以提供巨大帮助的地方:

const WithProducts = Comp => class WrappedComponent extends Component {
  getInitialState () {
    return { products: [] };
  }

  componentDidMount () {
    // connect to store, blah blah...
  }

  render () {
    return (
      <Comp products={this.state.products} {...this.props} />
    );
  }
}

const ProductListWithProducts = WithProducts( ProductList );

现在,我们包装的任何组件都将从商店接收产品列表作为 prop - 无需重复代码。不要重复自己。请注意,我是如何没有更改 ProductListProduct 组件来完成这项工作的:这些组件太笨了,不用关心。

您创建的任何 React 应用程序中的大多数组件都应该如此愚蠢。


另一方面,您不必担心多次调用您的商店。如果您担心这一点,那么 store 实现有问题,因为对 store 的调用应该是幂等的。您可以使用操作等来填充商店,但这应该完全独立于 商店获取值。设计良好的存储检索不应该有性能或网络损失(并且,再次使用像 Immutable 这样的库在这里也可以提供帮助)。

关于javascript - ReactJs - 可重用的 Redux 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34712755/

相关文章:

javascript - 如何创建仅遍历数据文件第 1 列和第 2 列的 d3 堆积条形图?

javascript - 可以用 `onEnter` 延迟组件渲染吗?

javascript - 在 react 中单击div时需要找到一个代码来调用两个函数

javascript - 访问 reducer 内的嵌套键

reactjs - DevSettings.reload() 用于在 React Native 中注销

javascript - 如何在 redux 中获取 ById

javascript - 使用 javascript 打开 shell

javascript - 动态加载图像。 Phaser.js

javascript - Chrome 为自定义 HTML 元素的 offsetWidth 返回 0

reactjs - React Hook 功能更新导致 eslint no-shadow 错误