javascript – ReactJs – 可重用的Redux服务

我理解Redux的操作,缩减器和映射到商店的概念.

我已经能够成功地将Redux执行到我的应用程序中.

我正在愉快地使用React的contextTypes来处理需要以前调用过的Redux数据的子组件.

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

因此,克服我的问题的唯一方法是映射到子项的父项中的商店,AGAIN,就像之前父项的更高组件,并将该数据作为道具传递给子项.

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

  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);

我看了容器,但在我看来,容器一次性包裹所有哑组件……

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

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

   <ProductsContainer>
      <ProductsDiscountedComponent />
   </ProductsContainer>

   <ProductsContainer>
      <ProductSpecialsComponent />
   </ProductsContainer>

   <ProductsContainer>
      <ProductsComponent />
   </ProductsContainer>

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

我找不到任何我能把握的解决方案.

题:

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

如果是这样,我们将不胜感激.

后脚本:

我或许如果我可以将’映射服务’作为纯粹的JavaScript函数执行,而只是在需要它的组件中导入该函数,这将解决问题,但我还没有看到任何Redux的例子正在映射的商店o / s React.

更新:

我在这里发布了解决方案……

React-Redux – Reuseable Container/Connector

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

现在让我们转向手头的问题.也许你并不完全是一个“愚蠢”的组成部分.一个愚蠢的组件应该是无国籍和纯粹的:

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

该组件从道具中获取所需的一切.现在有很多方法可以将数据导入到这个组件中,但它们都基于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>
    );
  }
}

从示例中可以看出,整个组件树将从简单的道具中获取其状态,这些道具从一个连接传递到商店.除App之外,所有组件都是哑巴,无状态和可预测的.

但也有一些情况,通过道具连接整个树是不切实际的,我们需要本地连接到我们的商店.这就是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 );

现在,我们所包装的任何组件都将从商店收到产品列表作为支柱 – 无需代码重复.不要重复自己.请注意我没有改变ProductList或Product组件以使其工作:这些组件太愚蠢而无法关注.

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

另外,您不应该担心不止一次打电话给您的商店.如果您对此感到担心,那么商店实施会出现问题,因为对商店的调用应该是幂等的.您可以使用操作等来填充商店,但这应该完全独立于从商店获取值.设计良好的商店检索应该没有性能或网络惩罚(同样,使用像Immutable这样的库也可以在这里帮助).

点赞