Bootstrap - creating columns within React, while rendering data - reactjs

I'm trying to render my JSON data in a bootstrap column format, ideally I would have 3 items on each row, with it wrapping to the next row. Right now, it's only rendering one item per row. Could someone point me in the right direction in terms of what I'm missing here?
Part of my component:
let parksJsx = ''
if (!parks) {
parksJsx = 'loading...'
} else {
parksJsx = parks.map(park => (
<Container key={park.Name}>
<Row>
<Col lg={4} className="park-data">
<h5>{park.Name}</h5>
<img src={park.Thumbnail}/>
<li>Location: {park.Location}</li>
<li>Est. {park.Established}</li>
<li>Area: {park.Area}</li>
<li>Recreation Visitors: {park['Recreation visitors']}</li>
<p>{park.Description}</p>
<br />
</Col>
</Row>
</Container>
))
}
return (
<div>
<h2 className="header">All U.S. National Parks:</h2>
<div className="park-container">
{parksJsx}
</div>
</div>
)
Current CSS:
.park-container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
}
.park-data {
flex: 0 1 auto;
}

Change your code to this:
let parksJsx = ''
if (!parks) {
parksJsx = 'loading...'
} else {
parksJsx = parks.map(park => (
<Col key={park.name} lg={4} className="park-data">
<h5>{park.Name}</h5>
<img src={park.Thumbnail}/>
<li>Location: {park.Location}</li>
<li>Est. {park.Established}</li>
<li>Area: {park.Area}</li>
<li>Recreation Visitors: {park['Recreation visitors']}</li>
<p>{park.Description}</p>
<br />
</Col>
))
}
return (
<div>
<h2 className="header">All U.S. National Parks:</h2>
<div className="park-container">
<Container>
<Row>
{parksJsx}
</Row>
</Container>
</div>
</div>
)
The problem was that you were rendering a container with a row per park item instead of putting all the park items inside one container with a row.
The solution was to move the container with row components out of the individual park items and put them outside the parks map.
If I could recommend some formatting, I'd suggest you implement your component as follows:
return (
<div>
<h2 className="header">All U.S. National Parks:</h2>
<div className="park-container">
{!parks ? 'loading...' :
<Container>
<Row>
{parks.map(park => (
<Col key={park.name} lg={4} className="park-data">
<h5>{park.Name}</h5>
<img src={park.Thumbnail}/>
<li>Location: {park.Location}</li>
<li>Est. {park.Established}</li>
<li>Area: {park.Area}</li>
<li>Recreation Visitors: {park['Recreation visitors']}</li>
<p>{park.Description}</p>
<br />
</Col>
))}
</Row>
</Container>
}
</div>
</div>
)
Then the logic is a lot easier to read from top to bottom.

First you need to separate the render function for a park and left there only a column with content, then you may try render all it in one row and it will work just fine because Row element has a display: flex .

Related

Scrolling to an element in a div with overflow set to scroll

I am building a time block with all the hours of the day the container only takes up 75vh and is set to scroll on overflow. I am trying to have the page load and scroll to the current time within my time block but I am having trouble figuring how to scroll within the div instead of the whole page. This works when I have the container set to 100vh but the overflow: scroll is creating a real issue for me. I see lots of answers for this issue in Angular an jQuery. But I am trying to do this in reactjs, and Im not sure how to target the scroll bar within my div.
onLoad I am calling this function:
const scrollToTime = () => {
const currentHour = moment().hour().toString()
const currentTimeEl = document.getElementById(currentHour)
window.scrollTo({
top: currentTimeEl.offsetTop,
behavior: "smooth"
})
}
I've thought of using Element.scrollTo() but this does not work.
This is a short snippet of what my container looks like:
<div className="dayView">
<hr className="day-divider1" />
<div className='dayView-timeSlot' id="12">
<Row className="time-row" >
<Col md="1" className="time-label">12:00 AM</Col>
<Col md="1" className="trash"><Trash /></Col>
<Col md="8" className="appointment-slot">
{" "}
</Col>
</Row>
</div>
<hr className="day-divider-dashed" />
<div className='dayView-timeSlot' id="12">
<Row className="time-row">
<Col md="1" className="time-label">12:30 AM</Col>
<Col md="1" className="trash"><Trash /></Col>
<Col md="8" className="appointment-slot">
{" "}
</Col>
</Row>
</div>
<hr className="day-divider1" />
...
</div>
.dayView{
height: 75vh;
overflow: scroll;
}
Is there a way to target the scroll within my dayView container?

react-bootstrap Carousel breaks when changing content during transition

video of issue:
When the carousel is transitioning from one slide to another, if another entry from a dataset is choosen, before the slide finishes its transition, the new images are rendered, but controls/timer are broken, so the carousel is not slidable any more (manually or automatically).
activeFish is a useState object with some fish data that gets changed with setActiveFish(newActiveFishDataObject) when a list item is clicked
Anyone have ideas for a solution?
<Carousel>
{activeFish['Image Gallery'].map((imageData, i) => (
<Carousel.Item key={imageData.title + i}>
<div className="image-container">
<img
className="d-block w-100"
src={imageData.src}
alt={imageData.alt}
/>
</div>
<Carousel.Caption>
<p>{imageData.title}</p>
</Carousel.Caption>
</Carousel.Item>
))}
</Carousel>
Replicate-
https://codesandbox.io/s/frosty-night-yckxro (thanks to #IgorGonak)
onload, immediately click the down arrow on the dropdown to expose options, mouse over option b, wait for transition to happen, click b rite in the middle of the transition. observe controls wont work for the 'b' dataset
I've created a dummy data with three entries and three images each entry. Then I built a select to select one and the carousel like yours - it is working on my side: When I choose another entry, the images in carousel are adjusted. The transition is working and is performed after each defined timeout:
https://codesandbox.io/s/frosty-night-yckxro
import React from "react";
import { Carousel, Form, Stack } from "react-bootstrap";
import data from "./fishData";
export default function App() {
const [activeFish, setActiveFish] = React.useState(data[0]);
const onSelect = (event) => {
const choosenFishName = event.target.value;
const choosenFish = data.find((fish) => fish.name === choosenFishName);
setActiveFish(choosenFish);
};
return (
<Stack className="m-3">
<Form.Group id="fish-select" className="mb-3" style={{ width: "18rem" }}>
<Form.Select value={activeFish.name} onChange={onSelect}>
{data.map((entry) => (
<option key={entry.name} value={entry.name}>
{entry.name}
</option>
))}
</Form.Select>
</Form.Group>
<p>Choosen fish is: {activeFish.name}</p>
<Carousel style={{ height: 200, width: 300 }}>
{activeFish["Image Gallery"].map((img) => {
return (
<Carousel.Item key={img.title}>
<img className="d-block w-100" src={img.src} alt={img.alt} />
<Carousel.Caption>{img.title}</Carousel.Caption>
</Carousel.Item>
);
})}
</Carousel>
</Stack>
);
}
Edit:
According to https://github.com/react-bootstrap/react-bootstrap/issues/6352 the problem here is that there is a state called "isSliding" in Carousel component. If it's true, the controls are deactivated. When we change children while sliding "isSliding" is true, but it's not set to false in the end, because the appropriate callback is never fired.
The solution is to reset the component by adding unique key to it:
<Carousel
key={activeFish.name}
interval={2000}
style={{ height: 200, width: 300 }}
>
{activeFish["Image Gallery"].map((img) => {
return (
<Carousel.Item key={img.title}>
<img className="d-block w-100" src={img.src} alt={img.alt} />
<Carousel.Caption>{img.title}</Carousel.Caption>
</Carousel.Item>
);
})}
</Carousel>

Put linebreak between components rendered with .map and boostrap

I´m rendering an array, every element of the array is showed with component "Post", but the elements are in the same line, I tried with
return (
<div style={{ height: 'calc(100vh - 65px)' }} className="d-flex justify-content-center align-items-center">
{posts.map((post) => {
return <Post key={post._id} post={post} />
})}
</div>
);
The component "Post" is the next:
I´m using Boostrap por the css styles
return (
{usuario.nombre}
Special title treatment
{texto}
Go somewhere
2 days ago
);
My result (All the elements are in horizontal position and I need them in vertical position):
The father component is root.
If I delete the css classes of the component "Post", teh problem remains.
Have you tried this.
return (
<div>
{posts.map((post) => {
return <><Post key={post._id} post={post} /><br /></>
})}
</div>
);
I only changed the class of div where I put the .map ;| adn the problem was solved.
className="container" instead className="d-flex justify-content-center align-items-center">

React Bootstrap Cards and CardDeck Components - responsive layout

I'm using React Bootstrap and am pulling data from an API using Axios. I'm trying to display the data from that API in bootstrap Card / CarDeck components. I have most of it working using the code below but I'm having problems with the layout.
I'd like to be able to have the card deck be responsive and show a flexible number of cards per row depending on the screen size. At the moment if there are lots of items in the response each card is ridiculously thin and can't be viewed. What is the correct way to do this?
import React, { useState, useEffect } from "react";
import CardDeck from "react-bootstrap/CardDeck";
import Card from "react-bootstrap/Card";
import axios from "axios";
import Container from "react-bootstrap/Container";
const CardColumns = () => {
const [cardInfo, setData] = useState([]);
console.log(cardInfo);
useEffect(() => {
axios
.get(
"https://webhooks.mongodb-realm.com/api/client/v2.0/app/cards-fvyrn/service/Cards/incoming_webhook/getAllCards"
)
.then((response) => {
setData(response.data);
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
}, []);
const renderCard = (card, index) => {
return (
<Card style={{ width: "18rem" }} key={index} className="box">
<Card.Img variant="top" src="holder.js/100px180" src={card.image} />
<Card.Body>
<Card.Title>
{index} - {card.manufacturer}
</Card.Title>
<Card.Text>{card.player}</Card.Text>
</Card.Body>
</Card>
);
};
return <CardDeck>{cardInfo.map(renderCard)}</CardDeck>;
};
export default CardColumns;
In the end this is the solution I went with the below. Key I think were:
Wrapping the cardDeck in <Container> and then wrapping the cards with <Col className="container-fluid mt-4">:
`
const renderCard = (card, index) => {
return (`
<Col className="container-fluid mt-4">
{/* <Card key={index} className="box"> */}
<Card style={{ width: "18rem" }} key={index} className="box">
<Card.Header>
{card.brand} - {card.series}
</Card.Header>
<Card.Img variant="top" src={card.front_image} fluid />
<Card.Body>
<Card.Title>
{card.player} (#
{card.card_number.$numberDouble}) {card.variation}
</Card.Title>
{/* <Card.Text className="d-flex">{card.player}</Card.Text> */}
{/* <Card.Text>{card.player}</Card.Text> */}
</Card.Body>
<ListGroup className="list-group-flush">
<ListGroupItem>
Print Run - {card.print_run.$numberDouble}
</ListGroupItem>
<ListGroupItem>Career Stage - {card.career_stage} </ListGroupItem>
<ListGroupItem>For Trade - {card.forTrade}</ListGroupItem>
</ListGroup>
<Card.Footer className="text-muted">{card.team}</Card.Footer>
</Card>
</Col>
//{/* </Col> */}
);
};
return (
<Container>
<Button variant="primary">Filter By Brand</Button>{" "}
<Button variant="primary">Filter By Player</Button>{" "}
<Button variant="primary">Filter By Team</Button>
<CardDeck>{cardInfo.map(renderCard)}</CardDeck>
</Container>
);`
Here are my suggestions for this issue:
Each card should have a min-width to ensure that they do not shrink below a certain amount. So instead of width: "18rem" try min-width: "18rem". If your CSS is properly set up it should cause other cards to overflow to the next row.
You can make use of media-queries or grid layout as mentioned to determine how many cards you want to show for various screen types based on their varying widths say see this link media-query-breakpoints react-bootstrap-grid
Also you can try using CSS flexbox layout, I have an article on this CSS Flex Box
Try to use a col-'n' to each card instead of a fix width.
...
import { Card, Col } from 'react-bootstrap';
...
<Col md="n"> // n must be your desired width like
<Card key={index} className="box">
...
</Col>
You can see more at: Bootstrap Card Sizing

style div next to and on top of each others

so i have divs created in react basically they are components and i want to style them using bootstrap like this:
div div div
div div
div div
so basically there are 5components,the top 3 should be small and stack next to each others with small margin. the middle two are bigger and they are under the right and left divs and the bottom ones the same as the middle divs.
i have tried doing like col-6 for the middle and col-4 for the top ones but they were all over the place and messy.
this is what i tried without using css just bootstrap:
<div className="container">
<div className="row">
<div className="col-lg-4">
<Card />
<ActualLineChart data={systolic}/>
<ActualLineChart data={Diastolic}/>
</div>
</div>
<div className="row">
<div className="col-lg-6">
<div>
<ActualBarChart data={systolicAndDiastolicAndPulseAverageNew}/>
</div>
<ActualScatterChart data={systolicAndDiastolicAndPulseAverageNew}/>
</div>
</div>
<div className="row">
<div className="col-lg-6">
<DistributionChart/>
<DistributionChart />
</div>
</div>
</div>
how can i do this behavior?
I am guessing that if you are using react-bootstrap you probably have already installed it and included react component in your app.js file using this
import { Container, Row, Col } from 'React-Bootstrap';
Then you can simply use this for your desired output.
<Container>
<Row>
<Col xs="4">
component 1
</Col>
<Col xs="4">
component 2
</Col>
<Col xs="4">
component 3
</Col>
</Row>
<Row className="justify-content-between">
<Col xs="4">
component 4
</Col>
<Col xs="4">
component 5
</Col>
</Row>
<Row className="justify-content-between">
<Col xs="4">
component 6
</Col>
<Col xs="4">
component 7
</Col>
</Row>
</Container>
Output will be look like this:

Resources