React-Redux - 可重用的容器/连接器 [英] React-Redux - Reuseable Container/Connector

查看:59
本文介绍了React-Redux - 可重用的容器/连接器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我完全迷失在 react-redux 容器(即连接器)的概念上,因为它没有按照我的预期运行.我的问题很直接,对我来说也是合理的,但我找不到一个写得很好的例子来说明如何完成它.

假设我们有一个连接到具有产品上下文的商店的 React 组件,我们将调用此组件 ProductContext.

此外,假设我们希望在整个应用程序中自由地重用 ProductContext,以避免在可能需要产品的每个其他组件上分派操作的样板代码.

这就是我的意思:

来自 DiscountuedProducts:

//用容器中的道具做一些事情</ProductContext >

来自季节性产品:

//用容器中的道具做一些事情</ProductContext >

从我在 react-redux 上看到的示例来看,在我看来,他们的容器将季节性产品和停产产品都集中在容器中.怎么可以复用?

来自 ProductContextComponent:

<停产产品/><季节性产品/></节>

让事情复杂化,同时试图对这个最令人沮丧的事情保持冷静,模糊的简洁"似乎是我收到的唯一回应.

这是我的ProductContext:

@connect(state => ({产品:state.productsReducer.products}))导出默认类 ProductContext 扩展组件 {构造函数(道具){超级(道具);}componentDidMount() {const { dispatch } = this.props;const clientId = this.context.clientInfo._id;dispatch(fetchProductsIfNeeded(clientId));}//从父节点获取静态上下文类型 = {客户端信息:PropTypes.object.isRequired};静态 propTypes = {孩子:PropTypes.node.isRequired,调度:PropTypes.func.isRequired,产品:PropTypes.array};使成为() {if (!this.props.products) 返回 ;.....返回 (//我想把产品数组放在这里);}};

那么我的想法是如果我这样做:

来自 DiscountuedProducts:

//用容器中的道具做一些事情</ProductContext >

DiscontinuedProducts 应该了解这些产品,它可以简单地过滤掉哪些已停产.

我完全错了吗?这不是合理的渴望吗?

如果有人知道网络上一个详尽的示例说明如何实现这一点,我将非常感谢您向我指出.我在这个问题上花了一个多星期,准备放弃 react-redux.

更新:以下使用 HOC 的非常巧妙的解决方案.

解决方案

我发现了一种比文档更实用的方法来利用 redux 中的重复数据.当它已经在更高级别完成一次时,在每个受祝福的组件上重复 mapToProps 和调度实例化对我来说是没有意义的,这就是解决方案.确保您的应用符合 Babel 6,因为我使用了装饰器.

1.我为上下文创建了一个高阶组件......

product-context.js:

 import React, { Component, PropTypes } from 'react';//还原从'react-redux'导入{连接};从'../../redux/actions/products-actions'导入{fetchProductsIfNeeded};

<小时>

//productsReducer 已经在 index.js w/configureStore 中@connect(state => ({产品:state.productsReducer.products}))导出默认函数 ProductContext(Comp) {返回 (类扩展组件{静态 propTypes = {孩子:PropTypes.node,调度:PropTypes.func.isRequired,产品:PropTypes.array};静态上下文类型 = {客户端信息:PropTypes.object.isRequired;};componentDidMount() {const { dispatch } = this.props;const clientId = this.context.clientInfo._id;dispatch(fetchProductsIfNeeded(clientId));}使成为() {if (!this.props.products) return (<div>Loading products ..</div>);返回 (<Comp products={ this.props.products }>{ this.props.children }</Comp>)}})}

2.使用 product-context.js 的组件

carousel-slider.js:

import React, { Component, PropTypes } from 'react';......从'../../../context/product-context'导入ProductContext;

<小时>

@Radium@ProductContext导出默认类 CarouselSlider 扩展组件 {构造函数(道具){超级(道具);}......静态 showSlideShow(carouselSlides) {carouselSlides.map((slide, index) => {......结果.push (......)});返回结果;}使成为() {const carouselSlides = this.props.products;const 结果 = CarouselSlider.showSlideShow(carouselSlides);返回 (<div id="Carousel" className="animation" ref="Carousel">{ 结果 }

);}}

就这样吧.我所需要的只是对产品上下文的装饰器引用,并且作为 HOC,它会返回带有产品属性的轮播组件.

我为自己节省了至少 10 行重复代码,并从较低的组件中删除了所有相关的 contextType,因为使用装饰器不再需要它.

希望这个真实世界的例子能帮到我,因为我讨厌 todo 例子.

I am completely lost on the react-redux container (ie connector) concept as it is not doing what I anticipated. My issue is straight forward, and to me reasonable, yet I cannot find a well written example of how to accomplish it.

Let us say we have a react component that connects to a store that has product context, and we will call this component ProductContext.

Furthermore, let's say we want to reuse ProductContext liberally throughout the app so as to avoid the boilerplate code of dispatching actions on every other component that may need products.

Illustratively this is what I mean:

from DiscountuedProducts:

<ProductContext >
   // do something with props from container
</ProductContext >

from SeasonalProducts:

<ProductContext >
   // do something with props from container
</ProductContext >

From the examples I see at react-redux, it appears to me that their containers lump both seasonal and discontinued products in the container itself. How is that reusable?

from the ProductContextComponent:

<section >
  <DiscontinuedProducts />
  <SeasonalProducts />
</section >

Complicating matters, while trying to keep a cool head about this most frustrating matter, "nebulous tersity" seems to be the only responses I receive.

So here is my ProductContext:

@connect(state => ({
   products: state.productsReducer.products
}))
export default class ProductContext extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    const { dispatch } = this.props;
    const clientId = this.context.clientInfo._id;
    dispatch(fetchProductsIfNeeded(clientId));
  }

 // get from parent
 static  contextTypes = {
    clientInfo: PropTypes.object.isRequired
  };

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


  render() {
    if (!this.props.products) return <Plugins.Loading />;
    .....
    return (
         // I want to put the products array here
      );
    }
 };

Then my thinking is if I do this:

from DiscountuedProducts:

<ProductContext >
   // do something with props from container
</ProductContext >

DiscontinuedProducts should have knowledge of those products and it can simply filter for what is discontinued.

Am I completely wrong on this? Is this not reasonable to desire?

If anyone knows of a exhaustive example on the Net demonstrating how this can be achieved, I would much appreciate it being pointed out to me. I have spent over a week on this issue and am about ready to give up on react-redux.

UPDATE: A very slick solution below with use of a HOC.

解决方案

I have found a more practical way of utilizing repetitive data from redux than the docs. It makes no sense to me to repeat mapToProps and dispatch instantiation on every blessed component when it was already done once at a higher level, and there inlies the solution. Make sure your app is Babel 6 compliant as I used decorators.

1. I created a higher order component for the context ....

product-context.js:

   import React, { Component, PropTypes } from 'react';
   // redux
   import { connect } from 'react-redux';
   import { fetchProductsIfNeeded }  from '../../redux/actions/products-actions';


    // productsReducer is already in state from index.js w/configureStore
    @connect(state => ({
      products: state.productsReducer.products
    }))
   export default function ProductContext(Comp) {
    return (
      class extends Component {
        static propTypes = {
          children: PropTypes.node,
          dispatch: PropTypes.func.isRequired,
          products: PropTypes.array
        };

        static contextTypes = {
         clientInfo: PropTypes.object.isRequired;
        };

        componentDidMount() {
          const { dispatch } = this.props;
          const clientId = this.context.clientInfo._id;
          dispatch(fetchProductsIfNeeded(clientId));
        }

        render() {
          if (!this.props.products) return (<div>Loading products ..</div>);
          return (
            <Comp products={ this.props.products }>
              { this.props.children }
            </Comp>
          )
        }
      }
    )
  }

2. component utilizing product-context.js

carousel-slider.js:

import React, { Component, PropTypes } from 'react';
......
import ProductContext from '../../../context/product-context';


@Radium
@ProductContext 
export default class CarouselSlider extends Component {

  constructor(props) {
    super(props);   }

  ......

  static showSlideShow(carouselSlides) {
    carouselSlides.map((slide, index) => {
       ......          
     results.push (
       ......
      )
    });
    return results;   
  }

  render() {
    const carouselSlides = this.props.products;
    const results = CarouselSlider.showSlideShow(carouselSlides);
    return (
      <div id="Carousel" className="animation" ref="Carousel">
        { results }
      </div>
    );   
  } 
}

So there you go. All I needed was a decorator reference to product-context, and as a HOC, it returns the carousel component back with the products prop.

I saved myself at least 10 lines of repetitive code and I removed all related contextType from lower components as it is no longer needed with use of the decorator.

Hope this real world example helps as I detest todo examples.

这篇关于React-Redux - 可重用的容器/连接器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆