Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
465 views
in Technique[技术] by (71.8m points)

javascript - How do I display 3 card components horizontally with react bootstrap and grids?

db.json

{
  "products": [
    {
      "id": 1,
      "name": "Moto G5",
      "quantity": 2,
      "price": 13000
    },
    {
      "id": 2,
      "name": "Racold Geyser",
      "quantity": 3,
      "price": 6000
    },
    {
      "id": 3,
      "name": "Dell Inspiron",
      "quantity": 4,
      "price": 50000
    },
    {
      "id": 4,
      "name": "Epson Printer",
      "quantity": 1,
      "price": 9500
    },
    {
      "name": "Lenovo G50",
      "quantity": 2,
      "price": 50000,
      "id": 5
    }
  ]
}

App.js

import React from 'react';
import {BrowserRouter as Router, Route, Switch, NavLink} from 'react-router-dom';
import AllProductsPage from './components/AllProductsPage';
import AddProductPage from './components/AddProductPage';
import ProductDetail from './components/ProductDetail';
import './App.css'
import {Provider} from 'react-redux';
import configureStore from './stores/configureStore';
import {loadProduct} from './actions/productActions';

export default class App extends React.Component {
  render() {

       const About=()=>(
              <div>
                  <h1>About : This application provides information about the products </h1>
              </div>
      );

      const Header = ()=>(
        <header>
            <NavLink to="/about" activeClassName="is-active" >About</NavLink>
            <NavLink to="/" exact={true} activeClassName="is-active" >Products</NavLink>
        </header>
    );

       
      const store = configureStore();
      //loading data from db.json and into the store through the reducers
      store.dispatch(loadProduct());

      return (
        <Provider store={store}>
          <Router>
              <Header/>
              <Switch>
                <Route path="/" exact={true} component={AllProductsPage} />
                <Route path="/about"  component={About}/>
                <Route path="/addProduct" component={AddProductPage} />
                <Route path="/ProductDetail" component={ProductDetail}/>
              </Switch>
          </Router>
        </Provider>
      );
  }
}

AllProductsPage.js

import React, { Component } from "react";
import { connect } from "react-redux";
import { bindActionCreators } from "redux";
import { Link } from "react-router-dom";
import ProductList from "./ProductList";
import * as productActions from "../actions/productActions";
import { Button } from "react-bootstrap";

class AllProductsPage extends Component {
  render() {
    return (
      <div>
        <h1>Product List - Using Redux</h1>
        <ProductList products={this.props.products} />
        <br />
        <Link to="/addProduct"><Button variant="primary">Add Product</Button>{" "}</Link>
      </div>
    );
  }
}

function mapStateToProps(state, ownProps) {
  return {
    products: state.products,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(productActions, dispatch),
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(AllProductsPage);

ProductList.js

import React from "react";
import Product from "./Product";
import { Container, Row, Col} from "react-bootstrap";

export default class ProductList extends React.Component {
  render() {
    var productNodes = this.props.products.map((product) => {
      return (
        <Product
          key={product.id}
          id={product.id}
          name={product.name}
          quantity={product.quantity}
          price={product.price}
        >
          {product.text}
        </Product>
      );
    });
    return (
      <div>
        <Container>
          <Row>
          <Col xs="4">
                {productNodes}
              </Col>
          </Row>
        </Container>
      </div>
    );
  }
}

Product.js

import React from "react";
import { Link } from "react-router-dom";
import { Prompt } from "react-router";
import { Card, Button } from "react-bootstrap";
export default class Comment extends React.Component {
  // eslint-disable-next-line
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <Card style={{ width: "18rem" }}>
      <Prompt message={location =>location.pathname.includes("/ProductDetail")?  `Are you sure you want to view the details ?` : true  } />
        <Card.Body>
          <Card.Title>
            {this.props.name}
          </Card.Title>
          <Card.Text>
            Quantity : {this.props.quantity}
          </Card.Text>
          <Card.Title>{this.props.price}</Card.Title>
          <Link to={{pathname: "/ProductDetail",productName:{name : this.props.name}}}>
            <Button variant="primary">View Product</Button>
          </Link>
        </Card.Body>
      </Card>
    );
  }
}

Now this is my first time using react-bootstrap. So i don't have much clue here.

What i want is like for the cards to be generated in such a way that there should be THREE cards in a row.

Now this is the code i've done so far, but I am confused on how i can make the cards horizontal, without writing <Col> three times, which repeats the same component 3 times in a row. Please help.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You need to split the data into rows, each one containing 3 cols, each one containing a product. You can solve this problem by using a chunk function, which takes an array and a chunk size as parameters and outputs an array containing all the chunks. There are many libraries that implement this (e.g. lodash) but for the sake of simplicity, just grab the chunk function from here.

Solution

  1. Copy or import a chunk function from a well-known library.
const chunk = (arr, chunkSize = 1, cache = []) => {
  const tmp = [...arr]
  if (chunkSize <= 0) return cache
  while (tmp.length) cache.push(tmp.splice(0, chunkSize))
  return cache
}
  1. Split your data into chunks of a fixed length.
const productsChunks = chunk(props.products, 3);
  1. Render each chunk as a row containing 3 columns, with your Product component inside.
const rows = productsChunks.map((productChunk, index) => {
    const productsCols = productChunk.map((product, index) => {
        return (
        <Col xs="4" key={product.id}>
          <Product key={product.id} quantity={product.quantity} price={product.price} name={product.name} />      
        </Col>
      );
    });
    return <Row key={index}>{productsCols}</Row>
});

That should solve your problem, let me know what you think about my solution. I've included a JSFiddle for clarity. My JSFiddle: Link


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...