【问题标题】:How to mapStateToProps only after the component receives data from Firebase如何仅在组件从 Firebase 接收数据后才映射StateToProps
【发布时间】:2019-09-09 21:36:40
【问题描述】:

在应用程序中,我尝试根据路由参数呈现数据。

当我运行代码时,我收到一个错误屏幕,因为 mapStateToProps 没有从 Firestore 接收到数据,并且 .find() 函数无法在“未定义”上运行。

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

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

我尝试在组件内部使用条件渲染,但错误出现在 mapStateToProps() 内部。数据甚至没有到达组件,因为脚本在第一次尝试将状态映射到它的 props 时就停止了。

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

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

【问题讨论】:

    标签: javascript reactjs firebase redux react-redux


    【解决方案1】:

    您应该在 mapStateToProps 函数中使用条件。检查您是否有数据,如果数据不可用,则返回一个空数组、对象或最适合您的东西。当状态发生变化时,函数再次映射到真正的交易。

    【讨论】:

    • 嘿,我刚刚对一小部分代码应用了条件渲染,并对其余部分进行了注释。我 console.logged this.props.product 并且它只返回一次未定义,在它从 Firebase 接收到的数据之前。因为那个组件没有被渲染。
    【解决方案2】:

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

    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>}
    

    【讨论】:

    • 嘿,我刚刚对一小部分代码应用了条件渲染,并对其余部分进行了注释。我 console.logged this.props.product 并且它只返回一次未定义,在它从 Firebase 接收到的数据之前。因为那个组件没有被渲染。
    • 您可以使用 setTimeout 来延迟或使用 setInterval 循环,直到有结果返回并清除间隔
    【解决方案3】:

    答案:

    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 语句。

    【讨论】:

      猜你喜欢
      • 2021-12-22
      • 2018-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-20
      • 1970-01-01
      相关资源
      最近更新 更多