Reactjs 组件在使用privateroute后停止重新渲染

Reactjs 组件在使用privateroute后停止重新渲染,reactjs,react-router-dom,Reactjs,React Router Dom,我在Reactjs(simple shop)中创建了第一个应用程序,在更改状态值后重新提交UI时遇到了一些问题。在App.js内部使用PrivateRoute之前,一切都正常工作。现在,当我单击“添加到卡”时,产品状态会发生变化(数量设置为1),但在UI上仍然为0(因此不会重新呈现组件)。 可能是因为我在App.js路由中使用的是component={ProductList},而不是render={()=>}。但render不再使用PrivateRoute(会引发错误)。我不确定我做错了什么,但

我在Reactjs(simple shop)中创建了第一个应用程序,在更改状态值后重新提交UI时遇到了一些问题。在App.js内部使用PrivateRoute之前,一切都正常工作。现在,当我单击“添加到卡”时,产品状态会发生变化(数量设置为1),但在UI上仍然为0(因此不会重新呈现组件)。 可能是因为我在App.js路由中使用的是component={ProductList},而不是render={()=>}。但render不再使用PrivateRoute(会引发错误)。我不确定我做错了什么,但我很难过,这是我第一次用reactjs写东西,所以我需要一些帮助

App.js

import React from 'react';
import './../App.css';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import Navbar from '../components/navbar';
import ProductList from '../components/productList';
import Checkout from '../components/checkout';
import Payment from '../components/payment';
import Footer from '../components/footer';
import SignIn from '../components/auth/signIn';
import SignUp from '../components/auth/signUp';
import { PrivateRoute } from '../components/auth/privateRoute';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      loggedIn: true,
      selectedProducts: [],
      products: [
        {
          "id": 1,
          "name": "11 bit studios SA",
          "grossPrice": 390.00,
          "netPrice": 360.00,
          "image": "https://jarock.pl/upload/posts/836323184026f846637c9e455b3950a4.jpg",
          "description": "",
          "quantity": 0
        },
        {
          "id": 2,
          "name": "PEKAO",
          "grossPrice": 108.00,
          "netPrice": 100.00,
          "image": "https://pbs.twimg.com/profile_images/1107386368609652736/U91cV_vU.png",
          "description": "",
          "quantity": 0
        },
        {
          "id": 3,
          "name": "CDPROJEKT",
          "grossPrice": 198.00,
          "netPrice": 170.00,
          "image": "https://yt3.ggpht.com/a/AGF-l7_JugJ8uDvDTXqsBPLuT4ZueARyKoM1dVG1gA=s900-mo-c-c0xffffffff-rj-k-no",
          "description": "",
          "quantity": 0
        },
        {
          "id": 4,
          "name": "CCC",
          "grossPrice": 147.00,
          "netPrice": 135.00,
          "image": "https://ccc.eu/start_page/assets/img/logo.jpg",
          "description": "",
          "quantity": 0
        }
      ]
    }

    this.AddItemToSelectedProductList = this.AddItemToSelectedProductList.bind(this);
    this.RemoveItemFromSelectedProductList = this.RemoveItemFromSelectedProductList.bind(this);
  }

  AddItemToSelectedProductList(newProduct) {
    var newProductList = this.state.selectedProducts;
    const existingProduct = newProductList.find(item => newProduct.id === item.id);

    if (existingProduct) {
      existingProduct.quantity++;

      this.setState((state) => ({
        products: state.products
      }));
    }
    else {
      newProduct.quantity = 1;
      newProductList.push(newProduct);
      this.setState({ selectedProducts: newProductList });
    }
  };


  RemoveItemFromSelectedProductList(productToRemove) {
    var newProductList = this.state.selectedProducts;
    if (newProductList.length > 0) {
      const productToRemoveIndex = newProductList.indexOf(productToRemove);
      newProductList.splice(productToRemoveIndex, 1);
      this.setState({ selectedProducts: newProductList });
    }

    var displayedProductList = this.state.products;
    const displayedProduct = displayedProductList.find(x => x.id === productToRemove.id);
    displayedProduct.quantity = 0;
    this.setState({ products: displayedProductList });
  };

  render() {
    return (
      <Router>
        <div className="main-div">
          <Navbar checkoutItems={this.state.selectedProducts} />
          <PrivateRoute exact path='/' component={ProductList} products={this.state.products} selectProductHandler={this.AddItemToSelectedProductList} />
          <PrivateRoute path="/checkout" component={Checkout} selectedProducts={this.state.selectedProducts} removeProductHandler={this.RemoveItemFromSelectedProductList} />
          <PrivateRoute path="/payment" component={Payment} />
          <Route path="/signin" component={SignIn} />
          <Route path="/signup" component={SignUp} />
        </div>
        <Footer />
      </Router>
    );
  }
}

export default App;
import React from 'react';
import { Route, Redirect } from 'react-router-dom';

export const PrivateRoute = ({ component, redirectTo, ...rest }) => {
  return (
    <Route {...rest} render={routeProps => {
      return localStorage.getItem('user') ? (
        renderMergedProps(component, routeProps, rest)
      ) : (
          <Redirect to={{
            pathname: '/signin',
            state: { from: routeProps.location }
          }} />
        );
    }} />
  );
};

const renderMergedProps = (component, ...rest) => {
  const finalProps = Object.assign({}, ...rest);
  return (
    React.createElement(component, finalProps)
  );
}

export const PropsRoute = ({ component, ...rest }) => {
  return (
    <Route {...rest} render={routeProps => {
      return renderMergedProps(component, routeProps, rest);
    }} />
  );
}

在React中,不允许对象突变,每次都必须创建新的对象副本

existingProduct.quantity++;
应该是

const newProduct = {...existingProduct, quantity: existingProduct.quantity + 1}

与此类似的问题是,您应该创建一个新的数组实例。

在修改类似于此UI的AddTopProducts后,再次正确地重新呈现:

AddToProducts(newProduct) {
    var newProductList = this.state.products.slice();
    const productIndex = newProductList.findIndex(item => item.id === newProduct.id);
    newProductList[productIndex].quantity = newProductList[productIndex].quantity + 1;

    this.setState({ products: newProductList });
}
我不确定这为什么不起作用(immerjs):


我已经更改了“添加到篮子”功能的实现,并使用immerjs来实现。但仍然没有重新呈现UI。当我查看状态值时,它们是正确的。
const newProduct = {...existingProduct, quantity: existingProduct.quantity + 1}
this.setState((state) => ({
  products: state.products
}));
AddToProducts(newProduct) {
    var newProductList = this.state.products.slice();
    const productIndex = newProductList.findIndex(item => item.id === newProduct.id);
    newProductList[productIndex].quantity = newProductList[productIndex].quantity + 1;

    this.setState({ products: newProductList });
}
AddToProducts(newProduct) {
   const nextState = produce(this.state.products, draft => {
      const productIndex = draft.findIndex(item => item.id === newProduct.id);
      draft[productIndex].quantity = draft[productIndex].quantity + 1;
    });
   this.setState({ products: nextState });
}