Как mapStateToProps только после того, как компонент получает данные из Firebase - PullRequest
0 голосов
/ 19 апреля 2019

В приложении я пытаюсь отобразить данные на основе параметров маршрута.

Когда я запускаю код, я получаю экран ошибки, потому что 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 ().Данные даже не попадают в компонент, потому что скрипт останавливается при первой попытке сопоставления состояния его реквизиту.

Вот мой компонент без условного рендеринга, для справки.

<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 голосов
/ 19 апреля 2019

вы можете использовать условие для проверки реквизита и рендеринга только при наличии. Обратите внимание на изменения, а также используйте тайм-аут для задержки возврата

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>}
0 голосов
/ 19 апреля 2019

Ответ:

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

Я использовал оператор if в mapStateToProps.

0 голосов
/ 19 апреля 2019

Вы должны использовать условие в вашей функции mapStateToProps. Проверьте, есть ли у вас данные или нет, и верните пустой массив, объект или вещь, которая подходит вам лучше всего, если данные недоступны. Когда состояние меняется, функция снова сопоставляется с реальной сделкой.

...