仅在组件从Firebase接收数据后,如何映射StateToProps

时间:2019-04-19 16:25:25

标签: javascript reactjs firebase redux react-redux

在应用程序中,我试图基于路由参数呈现数据。

运行代码时,我收到一个错误屏幕,因为mapStateToProps尚未从Firestore接收数据,并且.find()函数无法在'undefined'上运行。

const mapStateToProps = (state, ownProps) => {
  const id = ownProps.match.params.product_id;

  return {
    product: state.firestore.ordered.products.find(p => p.id === id)
  };
};

我尝试在组件本身内部使用条件渲染,但是错误在mapStateToProps()内部。数据甚至没有到达组件,因为脚本在首次尝试将状态映射到其道具时就停止了。

这是我的没有条件渲染的组件,仅供参考。

<div className="product-detail-page top-padding container col-lg-10">
        <div className="product-desc">
          <div className="product-desc-image col-lg-5">
            <img
              src={this.props.product.image}
              alt={this.props.product.name}
              className="col-12"
            />
          </div>
          <div className="product-desc-right col-lg-7">
            <h2 className="product-desc-title">{this.props.product.name}</h2>
            <div className="product-desc-bottom-section">
              <div className="product-desc-text">
                <p>
                  In stock - Ships from Ireland. Sold and Shipped by{" "}
                  <span className="comp-logo">
                    <Link to="/">
                      comp<span className="red-dot">.</span>com
                    </Link>
                  </span>
                </p>
                <ul>
                  <li>{this.randomDetails(1)}</li>
                  <li>{this.randomDetails(2)}</li>
                  <li>{this.randomDetails(3)}</li>
                  <li>{this.randomDetails(4)}</li>
                  <li>{this.randomDetails(5)}</li>
                  <li>{this.randomDetails(6)}</li>
                </ul>
                <div className="star-rating">
                  <img src={this.starRating(1)} alt="*" />
                  <img src={this.starRating(2)} alt="*" />
                  <img src={this.starRating(3)} alt="*" />
                  <img src={this.starRating(4)} alt="*" />
                  <img src={this.starRating(5)} alt="x" />
                </div>
              </div>
              <div className="product-desc-checkout">
                <div className="product-desc-total">
                  <h4>€ {this.preTaxCalculator().toFixed(2)}</h4>
                  <p>VAT - € {this.taxCalculator().toFixed(2)}</p>
                  <p>Shipping: € {this.props.product.shipping}</p>
                  <h3>{this.props.product.price}</h3>
                </div>
                <div className="product-desc-action-buttons">ADD TO CART</div>
                <div className="product-desc-action-buttons">
                  ADD TO WISHLIST
                </div>
                <div className="product-desc-action-buttons">
                  SAVE FOR LATER
                </div>
              </div>
            </div>
          </div>
        </div>
        <div className="product-details">
          <h2>Learn more about the {this.props.product.name}</h2>
          <table>
            <tbody>
              {this.renderKeys().map(key => (
                <tr key={key}>
                  <td>{key}</td>
                  <td>{this.props.product.details[key]}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

3 个答案:

答案 0 :(得分:0)

您应该在mapStateToProps函数中使用条件。检查是否有数据,如果没有数据,则返回一个空数组,对象或最适合您的东西。当状态发生变化时,该功能将再次以实际交易进行映射。

答案 1 :(得分:0)

您可以使用条件检查道具并仅在可用时进行渲染。注意更改,并利用超时延迟返回

const mapStateToProps = (state, ownProps) => {
  const id = ownProps.match.params.product_id;
setTimeout(()=>
  return {
    product: state.firestore.ordered.products.find(p => p.id === id)
  }),3000)
};

 {this.props.product && <div className="product-detail-page top-padding container col-lg-10">
                <div className="product-desc">
                  <div className="product-desc-image col-lg-5">
                    <img
                      src={this.props.product.image}
                      alt={this.props.product.name}
                      className="col-12"
                    />
                  </div>
                  <div className="product-desc-right col-lg-7">
                    <h2 className="product-desc-title">{this.props.product.name}</h2>
                    <div className="product-desc-bottom-section">
                      <div className="product-desc-text">
                        <p>
                          In stock - Ships from Ireland. Sold and Shipped by{" "}
                          <span className="comp-logo">
                            <Link to="/">
                              comp<span className="red-dot">.</span>com
                            </Link>
                          </span>
                        </p>
                        <ul>
                          <li>{this.randomDetails(1)}</li>
                          <li>{this.randomDetails(2)}</li>
                          <li>{this.randomDetails(3)}</li>
                          <li>{this.randomDetails(4)}</li>
                          <li>{this.randomDetails(5)}</li>
                          <li>{this.randomDetails(6)}</li>
                        </ul>
                        <div className="star-rating">
                          <img src={this.starRating(1)} alt="*" />
                          <img src={this.starRating(2)} alt="*" />
                          <img src={this.starRating(3)} alt="*" />
                          <img src={this.starRating(4)} alt="*" />
                          <img src={this.starRating(5)} alt="x" />
                        </div>
                      </div>
                      <div className="product-desc-checkout">
                        <div className="product-desc-total">
                          <h4>€ {this.preTaxCalculator().toFixed(2)}</h4>
                          <p>VAT - € {this.taxCalculator().toFixed(2)}</p>
                          <p>Shipping: € {this.props.product.shipping}</p>
                          <h3>{this.props.product.price}</h3>
                        </div>
                        <div className="product-desc-action-buttons">ADD TO CART</div>
                        <div className="product-desc-action-buttons">
                          ADD TO WISHLIST
                        </div>
                        <div className="product-desc-action-buttons">
                          SAVE FOR LATER
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <div className="product-details">
                  <h2>Learn more about the {this.props.product.name}</h2>
                  <table>
                    <tbody>
                      {this.renderKeys().map(key => (
                        <tr key={key}>
                          <td>{key}</td>
                          <td>{this.props.product.details[key]}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </div>}

答案 2 :(得分:0)

答案:

const mapStateToProps = (state, ownProps) => {
  const id = ownProps.match.params.product_id;
  if (state.firestore.ordered.products) {
    return {
      product: state.firestore.ordered.products.find(p => p.id === id)
    };
  }
};

我在mapStateToProps中使用了if语句。