无法在 ReactJs 中将一个页面重定向到另一个页面

Cannot redirect one page to another page in ReactJs

我正在制作一个功能,当我点击图像容器时,它将打开包含产品详细信息的页面,其中包含每个特定产品的确切详细信息。但是,当我点击图片时,没有任何反应!请帮我找出我的代码有什么问题,非常感谢!

Product.js:

class Product extends React.Component {
  render() {
    const { id, title, img, price, inCart } = this.props.product;
    return (
      <ProductWrapper clasName="col-9 mx-auto col-md-6 col-lg-3 my-3">
        <div className="card">
          <ProductContext.Consumer>
            {(value) => (
              <div className="img-container p-5">
                <Router>
                  <Link to="/details">
                    <img
                      src={img}
                      alt="product"
                      className="card-img-top"
                      onClick={() => {
                        value.handleDetail(id);
                      }}
                    />
                  </Link>
                </Router>
                <button
                  className="cart-btn"
                  onClick={() => value.addToCart(id)}
                  disabled={inCart ? true : false}
                >
                  {inCart ? (
                    <p className="text-capitalize mb-0">In Cart</p>
                  ) : (
                    <i class="fas fa-cart-plus"></i>
                  )}
                </button>
              </div>
            )}
          </ProductContext.Consumer>
          <div className="card-footer d-flex justify-content-between">
            <p className="align-self-center mb-0">{title}</p>
            <h5 className="text-blue mb-0">
              <span className="mr-1">$</span>
              {price}
            </h5>
          </div>
        </div>
      </ProductWrapper>
    );
  }
}

context.js:

class ProductProvider extends React.Component {
  state = {
    products: storeProducts,
    detailProduct: detailProduct
  };

  getItem = (id) => {
    const product = this.state.products.find((item) => item.id === id);
    return product;
  };

  handleDetail = (id) => {
    const product = this.getItem(id);
    this.setState(() => {
      return { detailProduct: product };
    });
  };
  addToCart = (id) => {
    console.log(`hello details. id is ${id}`);
  };
  render() {
    return (
      <ProductContext.Provider
        value={{
          ...this.state,
          handleDetail: this.handleDetail,
          addToCart: this.addToCart
        }}
      >
        {this.props.children}
      </ProductContext.Provider>
    );
  }
}

沙盒 link 为了更好地观察:https://codesandbox.io/s/why-cant-i-fetch-data-from-a-passed-value-forked-30bgi?file=/src/App.js

我推荐一种不同的方法,其中产品 ID 进入 URL 而不是在上下文中选择。这样做的一个主要好处是刷新详情页面意味着产品 ID 将被保留。

这里是link到a working CodeSandbox

下面是我所做的更改:

  1. 在上下文提供程序中,您可以删除 handleDetail,因为选择将改为存在于 URL:
class ProductProvider extends React.Component {
  state = {
    products: storeProducts,
    detailProduct: detailProduct
  };

  getItem = (id) => {
    const product = this.state.products.find((item) => item.id === id);
    return product;
  };

  addToCart = (id) => {
    console.log(`hello details. id is ${id}`);
  };
  render() {
    return (
      <ProductContext.Provider
        value={{
          ...this.state,
          addToCart: this.addToCart
        }}
      >
        {this.props.children}
      </ProductContext.Provider>
    );
  }
}
  1. App 组件中,更改 details 路由以采用 itemId 参数:
export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>

      <ProductProvider>
        <Router>
          <Switch>
            <Route exact path="/productlist" component={ProductList} />
            <Route path="/details/:itemId" component={Details} />
            <Route path="*" component={() => "404 Not Found"} />
          </Switch>
        </Router>
      </ProductProvider>
    </div>
  );
}
  1. 在您的产品组件中,使 Link 指向 details/itemId URL 并删除在上下文中设置该 ID 的任何需要:
class Product extends React.Component {
  render() {
    const { id, title, img, price, inCart } = this.props.product;
    return (
      <ProductWrapper clasName="col-9 mx-auto col-md-6 col-lg-3 my-3">
        <div className="card">
          <ProductContext.Consumer>
            {(value) => (
              <div className="img-container p-5">
                <Link to={`/details/${id}`}>
                  <img src={img} alt="product" className="card-img-top" />
                </Link>
                <button
                  className="cart-btn"
                  onClick={() => value.addToCart(id)}
                  disabled={inCart ? true : false}
                >
                  {inCart ? (
                    <p className="text-capitalize mb-0">In Cart</p>
                  ) : (
                    <i class="fas fa-cart-plus"></i>
                  )}
                </button>
              </div>
            )}
          </ProductContext.Consumer>
          <div className="card-footer d-flex justify-content-between">
            <p className="align-self-center mb-0">{title}</p>
            <h5 className="text-blue mb-0">
              <span className="mr-1">$</span>
              {price}
            </h5>
          </div>
        </div>
      </ProductWrapper>
    );
  }
}
  1. 最后,在 Details 组件中,从参数中删除 itemId 并从上下文中的产品列表中 find 正确的项目:
class Details extends React.Component {
  render() {
    const { itemId } = this.props.match.params;

    return (
      <ProductContext.Consumer>
        {(value) => {
          const selected = value.products.find(
            (p) => p.id === parseInt(itemId)
          );

          if (!selected) {
            return "Bad product ID: " + itemId;
          }

          const { id, company, img, info, price, title, inCart } = selected;

          return (
            <div className="container py-5">
              {/* title */}
              <div className="row">
                <div className="col-10 mx-auto text-center text-slanted text-blue my-5">
                  <h1>{title}</h1>
                </div>
              </div>
              {/* end of title */}
              <div className="row">
                <div className="col-10 mx-auto col-md-6 my-3">
                  <img src={img} className="img-fluid" alt="" />
                </div>
                {/* prdoduct info */}
                <div className="col-10 mx-auto col-md-6 my-3 text-capitalize">
                  <h1>model : {title}</h1>
                  <h4 className="text-title text-uppercase text-muted mt-3 mb-2">
                    made by : <span className="text-uppercase">{company}</span>
                  </h4>
                  <h4 className="text-blue">
                    <strong>
                      price : <span>$</span>
                      {price}
                    </strong>
                  </h4>
                  <p className="text-capitalize font-weight-bold mt-3 mb-0">
                    some info about product :
                  </p>
                  <p className="text-muted lead">{info}</p>
                  {/* buttons */}
                  <div>
                    <Link to="/productlist">
                      <ButtonContainer>back to products</ButtonContainer>
                    </Link>
                    <ButtonContainer
                      cart
                      disabled={inCart ? true : false}
                      onClick={() => {
                        value.addToCart(id);
                      }}
                    >
                      {inCart ? "in cart" : "add to cart"}
                    </ButtonContainer>
                  </div>
                </div>
              </div>
            </div>
          );
        }}
      </ProductContext.Consumer>
    );
  }
}