我正在使用React Router 4.
我有一个ShopCoffee组件,允许将项目添加到购物车。
点击购物车LINK React渲染购物车组件。
没有路由器(当购物车组件与主应用程序位于同一页面时),购物车工作正常。
但是另一个Cart组件(连接到路由器)没有收到道具,因此Cart呈现为空。
如果我再次点击LINK to Cart(购物车图标),它会重新呈现并显示所有项目。
所以,如果我像这样渲染组件:
<Cart itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} />
它可以正常工作,
但是当我这样做时:
const CartRoute = (props) => (<Cart itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} {...props} />);
仅当我在LINK标签上点击两次时才有效。
以下是代码:
app.jsx
import React from "react";
import ReactDOM from "react-dom";
import Main from "./components/main.component.jsx";
import { createStore } from "redux";
import { Provider } from "react-redux";
import { BrowserRouter, Route } from "react-router-dom";
var app = document.getElementById("app");
function mainAppReducer(state, action) {
if (!state) return {
items: []
}
switch (action.type) {
case 'ADD_TO_CART' : console.log('ADD_TO_CART');
console.log("action.items == ", action.items);
console.log("state==",state);
return Object.assign({}, action.items); // state уже содержит все данные об объектах в корзине, поэтому ничего не добавляем
case 'DELETE_FROM_CART' : console.log('DELETE_FROM_CART');
console.log("action.items == ", action.items);
console.log("state==",state);
return Object.assign({}, action.items); // state уже содержит все данные об объектах в корзине, поэтому ничего не добавляем
}
}
const store = createStore(mainAppReducer);
var render = () => ReactDOM.render(
<BrowserRouter>
<Provider store={store}>
<Route path="/" component = {Main} />
</Provider>
</BrowserRouter>
, app);
store.subscribe(render);
render();
main.component.jsx
import React from "react";
import Header from "./header.component.jsx";
import Footer from "./footer.component.jsx";
import Cart from "./cart.component.jsx";
import Checkout from "./checkout.component.jsx";
import ShopCoffee from "./shop-coffee.component.jsx";
import Rent from "./rent.component.jsx";
import Repair from "./repair.component.jsx";
import Contacts from "./contacts.component.jsx";
import ToCartButton from "./to-cart-button.component.jsx";
import { connect } from "react-redux";
import { Route, Switch } from "react-router-dom";
export class Main extends React.Component {
constructor(props) {
super(props);
this.addNewItemToCart = this.addNewItemToCart.bind(this);
this.deleteItemFromCart = this.deleteItemFromCart.bind(this);
this.state = {itemsInCart : []};
}
addNewItemToCart(itemsInCart) {
this.props.dispatch({type : 'ADD_TO_CART',
items: itemsInCart});
this.setState({itemsInCart : itemsInCart});
console.log("this.state", this.state);
}
deleteItemFromCart(i) {
var itemToDelete = this.state.itemsInCart[i];
console.log("itemToDelete == ", itemToDelete);
var itemsLeft = this.state.itemsInCart.filter((x,ind) => ind != i);
this.props.dispatch({type : 'DELETE_FROM_CART',
items: itemsLeft});
console.log("itemsLeft == ", itemsLeft);
this.setState({itemsInCart: itemsLeft});
}
getItemsInCart(itemsInCart) {
return itemsInCart;
}
render() {
const ShopCoffeeRoute = (props) => (<ShopCoffee itemsInCart = {this.state.itemsInCart} addNewItemToCart = {this.addNewItemToCart} {...props} />);
const CartRoute = (props) => (<Cart itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} {...props} />);
const CheckoutRoute = (props) => (<Checkout itemsInCart = {this.state.itemsInCart} {...props} />);
return (
<main>
<Header />
<Switch>
<Route exact path="/" render={ShopCoffeeRoute} />
<Route path="/rent" component={Rent} />
<Route path="/repair" component={Repair} />
<Route path="/contacts" component={Contacts} />
<Route path="/checkout" render={CheckoutRoute} />
<Route path="/cart" render={CartRoute} />
</Switch>
<Cart itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} />
<ToCartButton itemsInCart = {this.state.itemsInCart} />
<Footer />
</main>
);
}
}
export default connect((store) => store)(Main);
to-cart-button.component.jsx
import React from 'react';
import { Link } from "react-router-dom";
export default class ToCartButton extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Link to="/cart">
<section className="to-cart-button">
<div className="to-cart-button__text-container">
<p className="to-cart-button__text-container__text">
{this.props.itemsInCart.length}
</p>
</div>
</section>
</Link>
);
}
}
cart.component.jsx
import React from "react";
import { Link } from "react-router-dom";
export default class Cart extends React.Component {
constructor(props) {
super(props);
this.state = {itemsInCart : []};
}
componentWillReceiveProps(nextProps) {
if (nextProps.itemsInCart != this.state.itemsInCart) {
this.setState({itemsInCart : nextProps.itemsInCart});
}
}
deleteItemFromCart(i) {
var itemsLeft = this.state.itemsInCart.filter((x,ind) => ind != i);
this.props.deleteItemFromCart(i);
console.log("itemsLeft === ", itemsLeft);
this.setState({itemsInCart : itemsLeft});
}
render() {
console.log("Cart /");
console.log("this.props == ",this.props);
var imgPath = "img/coffee/"
var itemsInTable;
var itemsInCart = this.state.itemsInCart;
var totalPrice = 0;
if (!itemsInCart.length) {
itemsInTable = (<tr>
<td colSpan="5">Ваша корзина пуста</td>
</tr>);
}
else {
totalPrice = 0;
itemsInTable = (itemsInCart.map((item, i) => {
totalPrice += +item.price;
console.log("totalPrice==",totalPrice);
return (
<tr key={i}>
<td>{item.title}</td>
<td><img src={imgPath + item.image} /></td>
<td>1 шт.</td>
<td>{item.price} руб.</td>
<td><button className="cart__table__delete-button" onClick={this.deleteItemFromCart.bind(this, i)}><i className="fa fa-times"></i></button></td>
</tr>);
}));
}
return (
<section className="cart">
<div className="container">
<div className="row">
<div className="cart__title-container">
<h2 className="cart__title-container__title">
Ваша корзина
</h2>
</div>
</div>
<div className="row">
<div className="col-md-12">
<table className="cart__table">
<tbody>
<tr>
<th colSpan="5">Список товаров</th>
</tr>
{itemsInTable}
<tr>
<td></td>
<td></td>
<td>Итого:</td>
<td>{totalPrice} руб.</td>
<td></td>
</tr>
</tbody>
</table>
<div className="cart__next-button-container">
<Link to="/checkout"><button className="cart__next-button">Далее >></button></Link>
</div>
</div>
</div>
</div>
</section>
);
}
}
答案 0 :(得分:1)
答案 1 :(得分:0)
我想扩大alexfrize的回应。他引用了一个帖子指出:
在安装过程中,React不会使用初始道具调用componentWillReceiveProps。仅当组件的某些道具可能更新时,才调用此方法。在已安装的组件接收新道具之前,将调用componentWillReceiveProps()。
以上是什么意思?
如果您的代码依赖于componentWillReceiveProps()
来执行某项操作(即设置状态),则在使用React Router时,该方法不会在第一次单击Link
时触发。为了解决这个问题,您应该调用componentWillReceiveProps()
内部componentDidMount()
中的相同(或相似)代码。如有必要,请在componentDidMount()
中包含一些代码,以确保该代码具有抗错误性。