Javascript React.js error,Uncaught(in promise)error:元素可能未呈现给DOM
我有一个组件,它在我的电子商务应用程序中显示了我产品的全部细节,每次我打开不同的产品时,我在控制台中都会看到这个错误,这就是错误Javascript React.js error,Uncaught(in promise)error:元素可能未呈现给DOM,javascript,css,reactjs,Javascript,Css,Reactjs,我有一个组件,它在我的电子商务应用程序中显示了我产品的全部细节,每次我打开不同的产品时,我在控制台中都会看到这个错误,这就是错误 Uncaught (in promise) Error: Element is probably not rendered to the DOM - something with your layout or CSS definition at e.<anonymous> (index.tsx:197) at index.esm.js:51
Uncaught (in promise) Error: Element is probably not rendered to the DOM - something with your layout or CSS definition
at e.<anonymous> (index.tsx:197)
at index.esm.js:516
at Object.next (index.esm.js:516)
at s (index.esm.js:516)
class FullProduct extends Component {
state = {
purchasing: false,
favIcon: this.props.isFavourite,
isFavourite: this.props.isFavourite,
show: false,
isRemove: null,
showFedback: false,
isBasketAdd: false,
showBasketFedback: false
};
// get product data
loadData = () => {
if (this.props.match.params.id) {
if (
!this.props.product ||
(this.props.product &&
this.props.product.pid !== this.props.match.params.id)
) {
this.props.onGetFullProduct(this.props.match.params.id);
}
}
};
// get isFavourite info
getData = async () => {
db.collection("userFavourites")
.doc(this.props.user.uid)
.get()
.then(res => {
let favourites = res.data();
const isFavourite = favourites
? favourites[this.props.match.params.id]
: false;
if (isMount) {
this.setState({ isFavourite: isFavourite, favIcon: isFavourite });
}
})
.catch(err => {
if (isMount) this.setState({ error: err });
});
};
componentDidMount() {
isMount = true;
if (isMount) {
if (this.props.user) {
this.getData();
}
this.loadData();
}
}
componentWillUnmount() {
isMount = false;
}
componentDidUpdate() {
if (isMount) {
this.loadData();
}
}
discountHandler = (price, discount) => {
let newPrice = price - (price * discount) / 100;
return Math.round(newPrice * 100) / 100;
};
purchaseHandler = () => {
if (isMount) this.setState({ purchasing: true });
};
purchaseCancelledHandler = () => {
if (isMount) this.setState({ purchasing: false });
};
purchaseContinuedHandler = () => {
this.props.onCheckPurchasing();
if (this.props.user) {
this.props.history.push("/checkout");
}
};
loginBtnClicked = () => {
this.props.history.push("/login");
this.props.onCheckPurchasing();
};
registerBtnClicked = () => {
this.props.history.push("/register");
this.props.onCheckPurchasing();
};
onMouseEnterHandler = e => {
let fav = this.state.isFavourite;
fav = !fav;
if (isMount)
this.setState({
favIcon: fav
});
};
onMouseLeaveHandler = () => {
let fav = this.state.isFavourite;
if (isMount) this.setState({ favIcon: fav });
};
favBtnHandler = productId => {
if (this.props.user) {
let isFavourite = this.state.isFavourite;
if (isFavourite && isMount) {
this.setState({ isRemove: true });
} else {
this.setState({ isRemove: false });
}
if (isMount) this.setState({ isFavourite: !isFavourite });
db.collection("userFavourites")
.doc(this.props.user.uid)
.update({
[productId]: !isFavourite
})
.then(res => {
if (isMount) this.setState({ show: true });
setTimeout(() => {
if (isMount) this.setState({ show: false });
}, 5000);
})
.catch(err => {
let error = err.message.slice(0, 21);
if (error === "No document to update") {
db.collection("userFavourites")
.doc(this.props.user.uid)
.set({
[productId]: !isFavourite
})
.catch(err => {
if (isMount) this.setState({ error: err });
});
}
});
} else {
if (isMount) this.setState({ showFedback: true });
setTimeout(() => {
if (isMount) this.setState({ showFedback: false });
}, 5000);
}
};
loginClickedHandler = () => {
this.props.history.push("/login");
};
cancelClickedHandler = () => {
if (isMount) this.setState({ showFedback: false });
};
addToBasketHandler = () => {
let productId = this.props.product.pid;
let basketProductIds = [];
this.props.basketProducts.forEach(product =>
basketProductIds.push(product.pid)
);
let index = basketProductIds.findIndex(element => element === productId);
if (index === -1) {
this.props.onAddProductToBasket(this.props.product);
if (isMount)
this.setState({ isBasketAdd: true, showBasketFedback: true });
} else {
this.props.onRemoveProductFromBasket(this.props.product);
if (isMount)
this.setState({ isBasketAdd: false, showBasketFedback: true });
}
setTimeout(() => {
if (isMount) this.setState({ showBasketFedback: false });
}, 5000);
};
render() {
// get product image links
if (this.props.loaded) {
let images = this.props.product.images
.map(link => {
return link.match("/products/");
})
.map(link => {
const newlink = link.input.slice(link.index);
const newlink2 = newlink.slice(0, -4);
return { publicId: newlink2 };
});
// create gallery widget
const myWidget = window.cloudinary.galleryWidget({
cloudName: "e-bazaar",
container: "#my-gallery",
mediaAssets: images,
displayProps: {
mode: "classic"
},
transition: "slide",
themeProps: {
active: "#49c58f"
},
aspectRatio: "square",
zoomProps: {
trigger: "click"
},
carouselLocation: "left",
carouselStyle: "indicators",
indicatorProps: {
shape: "round"
}
});
myWidget.render();
}
// detail widget
let priceSection = null;
if (this.props.product) {
price = Math.round(this.props.product.price * 100) / 100;
priceSection = (
<p>
<span style={{ fontWeight: "bold", color: "#393D46" }}>Price: </span>
<span className={classes.Price}> {price.toFixed(2)}$</span>
</p>
);
if (this.props.product.discount) {
newPrice = this.discountHandler(
this.props.product.price,
this.props.product.discount
);
priceSection = (
<p className={classes.priceSection}>
<span className={classes.priceLabel}>Price:</span>
<span className={classes.Discount}>{price}$</span>
<span className={classes.Price}>{newPrice.toFixed(2)}$</span>
</p>
);
}
}
let fedback = (
<div className={classes.fedback}>
{this.state.isRemove ? (
<p>
Removed From Favourites <HiOutlineEmojiSad />
</p>
) : (
<p>
Added To Favourites <HiOutlineEmojiHappy />
</p>
)}
</div>
);
let basketFedback = (
<div className={classes.basketFedback}>
{!this.state.isBasketAdd ? (
<p>
Removed From Basket <HiOutlineEmojiSad />
</p>
) : (
<p>
Added To Basket <HiOutlineEmojiHappy />
</p>
)}
</div>
);
let favIcon = null;
if (this.state.isFavourite && !this.state.favIcon) {
favIcon = (
<BsHeart
style={{ color: "#626669" }}
id="icon"
className={classes.favIcons}
/>
);
} else if (this.state.isFavourite && this.state.favIcon) {
favIcon = (
<BsHeartFill
style={{ color: "#ff5e78" }}
id="icon"
className={classes.favIcons}
/>
);
} else if (!this.state.isFavourite && this.state.favIcon) {
favIcon = (
<BsHeartFill
style={{ color: "#ff5e78" }}
id="icon"
className={classes.favIcons}
/>
);
} else if (!this.state.isFavourite && !this.state.favIcon) {
favIcon = (
<BsHeart
style={{ color: "#626669" }}
id="icon"
className={classes.favIcons}
/>
);
}
let modal = (
<div className={classes.modalFedback}>
<p>
You have to login to your account, in order to add product to your
wishlist <HiOutlineEmojiHappy />
</p>
<Button btnType="Danger" clicked={this.cancelClickedHandler}>
CANCEL
</Button>
<Button btnType="Success" clicked={this.loginClickedHandler}>
LOGIN
</Button>
</div>
);
let detail = null;
if (this.props.product) {
detail = (
<div className={classes.detail}>
<h1 className={classes.title}>{this.props.product.title}</h1>
<p className={classes.desc}>{this.props.product.description}</p>
<p className={classes.brand}>
<span style={{ fontWeight: "bold", paddingRight: "10px" }}>
Brand:
</span>
{this.props.product.brand}
</p>
<p className={classes.amount}>
<span style={{ fontWeight: "bold", paddingRight: "10px" }}>
Amount:
</span>
{this.props.product.amount}
<span style={{ paddingLeft: "5px" }}></span>
available
</p>
{priceSection}
<div className={classes.ReviewSection}>
<Rating rating={this.props.product.rating} />
</div>
<div className={classes.MenuIcons}>
<span
className={classes.iconDiv}
onMouseEnter={e => this.onMouseEnterHandler(e)}
onMouseLeave={this.onMouseLeaveHandler}
onClick={() => this.favBtnHandler(this.props.match.params.id)}
>
{favIcon}
</span>
<span className={classes.iconDiv} onClick={this.addToBasketHandler}>
<Icon src={basket1} src2={basket2} />
</span>
<Button btnType="Primary" clicked={this.purchaseHandler}>
<FaShoppingCart /> SHOP NOW
</Button>
</div>
</div>
);
}
const screen = !this.props.loading ? (
<Aux>
<div id="my-gallery" className={classes.Gallery}></div>
{detail}
</Aux>
) : (
<Spinner />
);
let orderSummary = null;
if (this.props.product) {
orderSummary = (
<OrderSummary
product={this.props.product}
price={this.props.product.discount ? newPrice : price}
purchaseCancelled={this.purchaseCancelledHandler}
purchaseContinued={this.purchaseContinuedHandler}
/>
);
}
if (!this.props.user) {
orderSummary = (
<div>
<p className={classes.happyIcon}>
<HiOutlineEmojiHappy />
</p>
<p className={classes.noUserWarning}>
You have to login or create an account to complete your order...
</p>
<div className={classes.awayBtn}>
<Button btnType="Success" clicked={this.loginBtnClicked}>
LOGIN
</Button>
</div>
<div className={classes.awayBtn}>
<Button
btnType="Success"
clicked={this.registerBtnClicked}
className={classes.awayBtn}
>
REGISTER
</Button>
</div>
</div>
);
}
return (
<Aux>
<Modal
show={this.state.showFedback}
ModalClosed={this.cancelClickedHandler}
>
{modal}
</Modal>
{this.props.noProduct ? (
<NotFound />
) : (
<Aux>
<div className={classes.FullProduct}> {screen} </div>
<Modal
show={this.state.purchasing}
ModalClosed={this.purchaseCancelledHandler}
>
{orderSummary}
</Modal>
</Aux>
)}
{this.state.show ? fedback : null}
{this.state.showBasketFedback ? basketFedback : null}
</Aux>
);
}
}
const mapStateToProps = state => {
return {
productId: state.products.productId,
product: state.fullProduct.product,
loading: state.fullProduct.loading,
loaded: state.fullProduct.loaded,
error: state.fullProduct.error,
noProduct: state.fullProduct.noProduct,
user: state.auth.user,
isFavourite: state.products.isFavourite,
basketProducts: state.fullProduct.basketProducts
};
};
const mapActionsToProps = dispatch => {
return {
onGetFullProduct: id => dispatch(actions.getFullProduct(id)),
onCheckPurchasing: () => dispatch(actions.checkPurchasing()),
onAddProductToBasket: product =>
dispatch(actions.addProductsToBasket(product)),
onRemoveProductFromBasket: product =>
dispatch(actions.removeProductsFromBasket(product))
};
};
export default connect(
mapStateToProps,
mapActionsToProps
)(withRouter(FullProduct));
.FullProduct {
margin-top: 150px;
padding: 50px 10px 20px 10px;
display: flex;
align-items: flex-start;
flex-direction: row;
justify-content: center;
flex-wrap: wrap;
column-gap: 30px;
row-gap: 30px;
overflow: hidden;
}
.Gallery {
width: 35%;
padding: 20px;
border-radius: 10px;
box-shadow: rgba(36, 37, 38, 0.08) 0px 6px 15px 0px;
transition: all 0.3s cubic-bezier(.25, .8, .25, 1);
border: 1px solid white;
background-color: white;
margin: 0px 10px 20px 10px;
}
.detail {
width: 40%;
padding: 20px;
border-radius: 10px;
box-shadow: rgba(36, 37, 38, 0.08) 0px 6px 15px 0px;
transition: all 0.3s cubic-bezier(.25, .8, .25, 1);
border: 1px solid white;
background-color: white;
margin: 0 0 20px 0;
}
.title {
color: #393D46;
font-size: 3rem;
}
.desc {
color: #9fa4af;
text-align: left;
white-space: pre-wrap;
}
.brand {
color: #393D46;
}
.amount {
color: #393D46;
}
.priceLabel {
font-weight: bold;
color: #393D46;
padding-right: 10px;
}
.Price {
font-size: 2.5rem;
color: #45C48B;
margin: 20px 7px;
}
.Discount {
font-size: 1.8rem;
color: #9ba5af;
text-decoration: line-through;
text-decoration-color: #172B4D;
text-decoration-thickness: 3px;
}
.ReviewSection {
margin: 20px 0;
}
.iconDiv {
display: inline-block;
position: relative;
top: 10px;
}
.fedback {
background: #ff5e78;
padding: 0px 5px;
border-radius: 10px;
position: fixed;
z-index: 80;
right: 25px;
bottom: 50px;
}
.fedback>p {
color: white;
margin: 10px 5px;
font-size: large;
}
.basketFedback {
background: #45C48B;
padding: 0px 5px;
border-radius: 10px;
position: fixed;
z-index: 80;
right: 25px;
bottom: 50px;
}
.basketFedback>p {
color: black;
margin: 10px 5px;
font-size: large;
}
.modalFedback {
background: white;
padding-bottom: 20px;
}
.modalFedback>p {
font-size: larger;
margin-bottom: 40px;
}
.favIcons {
font-size: 30px;
padding-right: 10px;
}
.iconDiv img {
display: inline-block;
padding-right: 10px;
width: 30px;
height: 30px;
}
.noUserWarning {
margin: 40px 20px;
}
.happyIcon {
font-size: xx-large;
color: #393D46
}
.awayBtn {
display: inline-block;
}
@media(max-width:730px) {
.detail {
width: 80%;
}
.Gallery {
width: 80%;
}
}
@media(max-width:389px) {
.priceLabel {
display: block;
}
.Discount {
display: block;
}
.Price {
display: block;
}
}
@media(max-width:280px) {
.iconDiv {
top: -10px;
}
.awayBtn {
margin: 10px 0;
}
}