反应redux的两个组成部分

时间:2019-12-04 03:39:12

标签: reactjs redux

我有一个组件将显示来自后端的产品,还有一个组件将接收要过滤的产品,但是我怀疑通过redux接收我的产品列表。

我应该为我的过滤器组件接收吗? 还是应该返回与我在产品组件中获得的相同的东西? 还是应该创建一个操作来过滤我已经需要的内容?

我的家

    return (
      <div className="container">
      <h1>Shopping</h1>
      <hr />
      <div className="row">
        <div className="col-md-3"><Filters/></div>
        <div className="col-md-9"><Products/></div>
      </div>
    </div>
  )

我的组件产品:

import React, { Component } from 'react'
import {connect} from 'react-redux'
import { ProductsFetchData } from '../../store/actions/productsFetch';
import util from '../../util';
class HomeProducts extends Component {
    componentDidMount() {
        this.props.fetchData('/products');
      }
    render() {
      const productItems = this.props.products.map( product => (
          <div className="col-md-4 pt-4 pl-2">
          <div className = "thumbnail text-center"> 
          <a href={`#${product.id}`}  onClick={(e)=>this.props.handleAddToCard(e,product)}>
              <p>
                  {product.name}
              </p>
          </a>
          </div>
              <b>{util.formatCurrency(product.price)}</b>
              <button className="btn btn-primary" onClick={(e)=>this.props.handleAddToCard(e,product)}>Add to Cart</button>
          </div>
      )
      )
        return (
            <div className="container">
            <div className="row">
                {productItems}
            </div>  
            </div>
        )
    }
}
const mapStateToProps = (state) => {
    return {
        products: state.Products,
        hasErrored: state.ProductsHasErrored,
        isLoading: state.ProductsIsLoading
    };
  };
  const mapDispatchToProps = (dispatch) => {
    return {
        fetchData: () => dispatch(ProductsFetchData())
    };
  };
export default connect(mapStateToProps, mapDispatchToProps)(HomeProducts);

我的组件过滤器

import React, { Component } from 'react';
import './style.css'
class FilterHome extends Component {
    render() {
        return (
            <>
                <div className="row">
                    <button className="filterbt btn btn-danger btn-rounded">Filters</button>

                    <div className=" mt-4 d-flex flex-column">

                        <p className="textCategory">CATEGORY</p>
                        <div className="category d-flex flex-column">
                            <a href="" className="text-decoration-none"><p>Stat Trak</p></a>
                            <a href="" className="text-decoration-none"><p>Normal</p></a>
                        </div>

                        <p className="textCategory">EXTERIOR</p>
                        <div className="category d-flex flex-column">
                            <a href="" className="text-decoration-none"><p>Factory New ()</p></a>
                            <a href="" className="text-decoration-none"><p>Minimal Wear ()</p></a>
                            <a href="" className="text-decoration-none"><p>Field Tested ()</p></a>
                            <a href="" className="text-decoration-none"><p>Well Worn ()</p></a>
                            <a href="" className="text-decoration-none"><p>Battle Scarred ()</p></a>
                        </div>

                    </div>
                </div>
            </>
        )
    }
}

export default FilterHome;

2 个答案:

答案 0 :(得分:1)

1. redux-state :这是所有api响应的注册点(来自后端的所有数据都在此处存储为prestine,当您将mapStateToProps用作任何容器的props )。

2. 本地状态:这仅存在于您的容器及其所有子组件中。

3. 过滤器

a)来自服务器

您向服务器发出请求,并获得过滤产品的响应。这个   比较实用。   例如:您有 / products?page = 1 ,并且要按某个类别进行搜索,让我们     由特定公司说。根据您目前的数据(第1页),   可能只有1个,甚至没有与该公司相关的产品,但实际上服务器上有n个相同公司的产品可用。所以这只能假设为   最实用的方法。

b)从本地州过滤

如果这是您要实现的目标, 1.您只需要一个容器,HomeProducts 2.使ProductItems作为组件。我们将重用此组件以同时渲染两者。

**您将过滤器写为一个独立的容器。但是这些过滤器功能应在主页本身内提供。是不是,我的意思是您是从主页本身进行过滤,而不是从其他页面进行过滤。如果是这样,请将其添加到首页本身

1。主页

import React, { Component } from 'react'
import {connect} from 'react-redux'
import { ProductsFetchData } from '../../store/actions/productsFetch';
import util from '../../util';
import ProductItems from '<<..your relative path>>'
import FilterHome from '<<..your relative path>>'


class HomeProducts extends Component {
    constructor(props) {
      super(props)
      this.state = {
        productList: null,
      }
    }

    componentDidMount() {
        //this.props.fetchData('/products');
        this.props.fetchData('page=1');
    }

    componentWillReceiveProps(nextProps) {
      const { productList } = this.state
      const { products } = this.props

      // this only handles when local state is empty. add your logic here..
      !productList && this.setState(prevState => ({
        ...prevState,
        productList: products,
      }))
    }

    handleFilter = (category) => {
      // if it's an api call
      const { fetchData }  = this.props
      fetchData(`page=1&category=${category}`)

      //or you simply want to filter this local state(not-recommended)
      const { products } = this.props
      const productsList = [...products].filter(item => item.category === category)

      this.setState(prevState => ({
        ...prevState,
        productsList,
      }))
    }

    render() {
      const { productList } = this.state
      const { handleFilter } = this

      return (
          <div className="container">

            <FilterHome {...{ handleFilter }} />

            <ProductItems {...{ productsList }} />
          </div>
      )
    }
}
const mapStateToProps = (state) => {
  return {
    products: state.Products,
    hasErrored: state.ProductsHasErrored,
    isLoading: state.ProductsIsLoading
  };
};

//it may not suit depends on your api, but you get the idea..
const mapDispatchToProps = (dispatch) => {
  return {
    // fetchData: () => dispatch(ProductsFetchData())
    fetchData: params => dispatch(ProductsFetchData(`/products?${params}`))
  };
};

export default connect(mapStateToProps, mapDispatchToProps)(HomeProducts);

2.ProductItems

import React from 'react'

const ProductItem = ({ product }) => {
  return (
    <div className="col-md-4 pt-4 pl-2">
      <div className = "thumbnail text-center"> 
      <a href={`#${product.id}`}  onClick={(e)=>this.props.handleAddToCard(e,product)}>
          <p>
              {product.name}
          </p>
      </a>
      </div>
      <b>{util.formatCurrency(product.price)}</b>
      <button className="btn btn-primary" onClick={(e)=>this.props.handleAddToCard(e,product)}>Add to Cart</button>
    </div>
  )
}

const ProductItems = ({ productList }) => {
  return (
    <div className="row">      
      {productList && productList.map(product => <ProductItem key={product.id} {...{ product }} />)}  
    </div>
  )
}

export default ProductItems

3.FilterHome

import React from 'react'

const FilterHome = ({ handleFilter }) => {
  return (
    <div className="row">
      <button className="filterbt btn btn-danger btn-rounded">Filters</button>

      <div className=" mt-4 d-flex flex-column">

        <p className="textCategory">CATEGORY</p>
        <div className="category d-flex flex-column">
          <a href="" className="text-decoration-none" onClick={() => handleFilter('stat_trak')}><p>Stat Trak</p></a>
          <a href="" className="text-decoration-none" onClick={() => handleFilter('normal')}><p>Normal</p></a>
        </div>

        <p className="textCategory">EXTERIOR</p>
        <div className="category d-flex flex-column">
          <a href="" className="text-decoration-none" onClick={() => handleFilter('factory_new')}><p>Factory New ()</p></a>
          <a href="" className="text-decoration-none" onClick={() => handleFilter('minimal_wear')}><p>Minimal Wear ()</p></a>
          <a href="" className="text-decoration-none" onClick={() => handleFilter('field_tested')}><p>Field Tested ()</p></a>
          <a href="" className="text-decoration-none" onClick={() => handleFilter('well_worn')}><p>Well Worn ()</p></a>
          <a href="" className="text-decoration-none" onClick={() => handleFilter('battle_scarred')}><p>Battle Scarred ()</p></a>
        </div>

      </div>
    </div>
  )
}

export default FilterHome

我大致重写了它,可能包含错误。

答案 1 :(得分:0)

首先将其添加到本地状态,然后调用过滤器组件。

handleFilter = (category) => {
 const { Products } = this.state
 const products = {...Products}
 //or depends on the type, so it wont mutate the real data>> const products = [...Products]

 return products.filter(item => item.category === category)
}

这是您的评论所能理解的。是吗?