反应路由器-需要单击LINK两次以将道具传递给组件 [英] React router - Need to click LINK twice to pass props to Component

查看:72
本文介绍了反应路由器-需要单击LINK两次以将道具传递给组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用React Router 4。



我有一个ShopCoffee组件,可以将商品添加到购物车中。



通过单击购物车,LINK React渲染购物车组件。



没有路由器(当购物车组件与主应用程序位于同一页面时),购物车可以正常工作。 p>

但是另一个Cart组件(连接到路由器)不接收道具,因此Cart呈现为空。



如果我再单击一次链接到购物车(购物车图标),它将重新显示并显示所有项目。





因此,如果我渲染组件像这样:

 <购物车itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} /> 

它可以正常工作,



但是当我这样做:

  const CartRoute =(props)=> (<购物车itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} {... props} />); 



仅当我单击时有效



这是代码:



app.jsx

  import从反应进行反应; 
从 react-dom导入ReactDOM;

import main from ./components/main.component.jsx;
import {createStore} from redux;
从 react-redux导入{提供者};
import {BrowserRouter,Route} from react-router-dom;

var app = document.getElementById( app);

函数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); // //说明ужесодержитобобъектахвкорзине,поэтомуничегонедобавляем

案例控制台:DELETE_FROM_CART:(FART_CROM)
console.log( action.items ==,action.items);
console.log( state ==,state);
return Object.assign({},action.items); // //说明ужесодержитвседанныеобобъектахвкорзине,
var render =()=> ReactDOM.render(
< BrowserRouter>
<提供程序存储= {store}>
<路由路径= /组件= {Main} />
< / Provider>
< / BrowserRouter>
,app);
store.subscribe(render);
render();

main.component.jsx

  import从反应中反应; 
从 ./header.component.jsx导入标题;
从 ./footer.component.jsx导入页脚;
从 ./cart.component.jsx导入购物车;
从 ./checkout.component.jsx导入Checkout;
从 ./shop-coffee.component.jsx导入ShopCoffee;
从 ./rent.component.jsx导入租金;
从 ./repair.component.jsx导入修复;
从 ./contacts.component.jsx导入联系人;
从 ./to-cart-button.component.jsx导入ToCartButton;
import {connect}来自 react-redux;
import {Route,Switch} from react-router-dom;

出口类Main扩展了React.Component {
构造函数(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({类型: DELETE_FROM_CART,
个项目:itemLeft});
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)=> (<购物车itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} {... props} />);
const CheckoutRoute =(props)=> (<结帐itemsInCart = {this.state.itemsInCart} {... props} />);
return(
< main>
< Header />
< Switch>
<路由精确路径= / render = {ShopCoffeeRoute} />
<路由路径= / rent组件= {出租} />
<路由路径= / repair组件= {修复} />
< ; Route path = / 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} />
<页脚/>
< / main>
);
}
}

导出默认值connect((store)=> store)(Main);

to-cart-button.component.jsx

  import从'react'进行React; 
import {Link} from react-router-dom;

导出默认类ToCartButton扩展了React.Component {
构造函数(props){
超级属性(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从反应进行反应; 
import {Link} from react-router-dom;

导出默认类Cart扩展了React.Component {
构造函数(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 /咖啡/
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>
<链接到= / checkout><按钮className = cart__next-button>Далее>>< / button>< / Link>
< / div>
< / div>
< / div>
< / div>
< / section>
);
}
}


解决方案

找到解决方案:
反应路由器4-componentWillReceiveProps()不会't fire



感谢 Mayank Shukla


I'm using React Router 4.

I have a ShopCoffee component which allows to add items to Cart.

By clicking Cart LINK React renders Cart component.

Without Router (when Cart component is on the same page as main app), Cart works fine.

But another Cart component (which is attached to the router) doesn't recieve props, so the Cart renders as empty.

If I click LINK to Cart (cart icon) one more time, it rerenders and shows all items.

So, if I render component like this:

<Cart itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} />

it works correctly,

but when I do this:

const CartRoute = (props) => (<Cart itemsInCart = {this.state.itemsInCart} deleteItemFromCart = {this.deleteItemFromCart} {...props} />);

it works only if I click twice on LINK tag.

Here is the code:

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

解决方案

The solution was found: React Router 4 - componentWillReceiveProps() doesn't fire

Thanks to Mayank Shukla

这篇关于反应路由器-需要单击LINK两次以将道具传递给组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆