How to make images fit the page in React/Bootstrap? - javascript

I am using a function that maps every item in the props array to creating an image tag. I am trying to make every 3 images have a row div around them using bootstrap so they will fit the page correctly, but I cannot figure out how to do it. Any help would be appreciated. Here is the code:
import React, { Component } from 'react';
import "./Skills.css";
export default class Skills extends Component {
static defaultProps = {
images: [
"https://upload.wikimedia.org/wikipedia/commons/thumb/6/61/HTML5_logo_and_wordmark.svg/1200px-HTML5_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/CSS3_logo_and_wordmark.svg/1200px-CSS3_logo_and_wordmark.svg.png",
"https://upload.wikimedia.org/wikipedia/commons/6/6a/JavaScript-logo.png",
"https://p7.hiclipart.com/preview/306/37/167/node-js-javascript-web-application-express-js-computer-software-others.jpg",
"https://bs-uploads.toptal.io/blackfish-uploads/skill_page/content/logo_file/logo/5982/express_js-161052138fa79136c0474521906b55e2.png",
"https://webassets.mongodb.com/_com_assets/cms/mongodb_logo1-76twgcu2dm.png",
"https://www.pngfind.com/pngs/m/430-4309307_react-js-transparent-logo-hd-png-download.png",
"https://botw-pd.s3.amazonaws.com/styles/logo-thumbnail/s3/012015/bootstrap.png?itok=GTbtFeUj",
"https://sass-lang.com/assets/img/styleguide/color-1c4aab2b.png"
]
}
photo() {
return (
<div >
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
);
}
render() {
return (
<div id="skills-background" className="mt-5">
<div id="skills-heading" className="text-center">Skills I've Learned:</div>
<div className="container">
<div className="row">
{this.photo()}
</div>
</div>
</div>
)
}
}
CodeSandbox

I think, I found the issue,
<div> <-----This div is the issue
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</div>
You have wrapped your col-md-4 with a div, and div has display: block style, so you are getting every image on separate row. Simply replace div with Fragments,
<> <-----Make it Fragment
{this.props.images.map(image => (
<div className="col-md-4">
<img className="photo" src={image} />
</div>
))}
</>

Related

Passing data between child components in React

My goal is to use an onClick function in one of my components, and pass that data to another component (end goal is that in the other component called Playlist, it updates an array with the id of the clicked item).
I am just not sure how to pass the information between child components
My main component (app.jsx) looks like this
const mainCards = Data.map(card => {
return(
<MainCard
key={card.id}
id={card.id}
image={card.url}
title={card.title}
playbutton={card.playbutton}
addbutton={card.addbutton}
/>
)
})
const sideCards = SideData.map(card => {
return(
<SideCard
image={card.sideurl}
key={card.id}
title={card.sidetitle}
playbutton={card.playbutton}
addbutton={card.addbutton}
/>
)
})
return (
<div className="App">
<Navbar />
<Header />
<Playlist />
<CardContainer />
<div className="maincards">
{mainCards}
</div>
<div className="sidecards">
{sideCards}
</div>
</div>
)
}
export default App
The component where I am using onClick (MainCard.jsx)
const handleAdd = (id) => {
console.log(id)
}
return(
<div className="mainCardObject">
<div className="cardObj">
<img src={props.image} className ="mainCardImage"/>
<img src={props.playbutton} className="playbutton"/>
<img src={props.addbutton} onClick={() => handleAdd(props.id)} className="addbutton" />
</div>
</div>
)
}
export default MainCard
and the component I wish to pass information to (nothing inside, as I dont know where to start)
return(
<div className="playlistContainer">
<ul>
<li></li>
</ul>
</div>
)
}
export default Playlist```
My suggestion is that you manage 'ids array' state globally creating a context, using the hook useContext(). Here a link with a simple explanation. I hope it helps!
https://www.w3schools.com/react/react_usecontext.asp

ReactJS, onScroll doesn't work for dynamic navbar

I'm trying to make a navbar visible only when the user passes the header section. I set up a simple function to be triggered by "onScroll". However it's not really working.
Component:
function App() {
const [productArray, setProductArray] = useState([]);
const [navBarClass, setNavBarClass] = useState("hidden");
const navBarScroll = () => {
setNavBarClass("visible");
}; // this should make the navbar visible
return (
<div className="App">
<Header onScroll={navBarScroll} /> // Here's the onScroll
<ProductContainer
productArray={productArray}
setProductArray={setProductArray}
/>
<About />
<Footer />
<NavBar className={navBarClass} /> // This is the nav bar
</div>
);
}
Header Component:
const Header = () => {
return (
<div className="header" id="home">
<div className="header-sub">
<div className="div-1">
<img src={logo} alt="logo" className="logo" />
<div className="menu">
Home
About
Shop
Contact
<ShoppingCartIcon className="btn" />
<p></p>
</div>
</div>
<div className="div-2">
<FadeIn transitionDuration="2500">
<h1>AS UNIQUE AS YOU ARE.</h1>
</FadeIn>
</div>
<div className="div-3"></div>
</div>
</div>
);
};
Issue is onScroll is not being consumed in Header component. We need to add onScroll event on HTML tag in order for it to be invoked.
You can read onScroll prop in Header component and pass it to parent div as below and it should get called:
const Header = ({onScroll}) => {
return (
<div className="header" id="home" onScroll={onScroll}>
<div className="header-sub">
<div className="div-1">
<img src={logo} alt="logo" className="logo" />
<div className="menu">
Home
About
Shop
Contact
<ShoppingCartIcon className="btn" />
<p></p>
</div>
</div>
<div className="div-2">
<FadeIn transitionDuration="2500">
<h1>AS UNIQUE AS YOU ARE.</h1>
</FadeIn>
</div>
<div className="div-3"></div>
</div>
</div>
);
};

extends/inherit parent component in function

export default function PageTemplate() {
return (
<div className="layout">
<LeftMenu />
<div className="content">
<TopMenu />
<div id="other-contents">
// Contents goes here
</div>
</div>
</div>
);
}
export default function Index() {
return (
<div className="layout">
<LeftMenu />
<div className="content">
<TopMenu />
<div id="other-contents">
<h2>I am Index Page<h2/>
</div>
</div>
</div>
);
}
As you can see most of my contents goes in #other-contents, I will be repeating PageTemplate for every page, I wondering if there is way to just re-use PageTemplate. Instead of repeating code, I would just do something like extends/inherit/whatever possible and reduce the code in Index
I believe this is easier achieved with Class Based Component. But I am wondering if there could function based solution
React prefers Composition over Inheritance. Use the children prop all react components have.
export default function PageTemplate({ children }) {
return (
<div className="layout">
<LeftMenu />
<div className="content">
<TopMenu />
<div id="other-contents">
{children}
</div>
</div>
</div>
);
}
Usage:
<PageTemplate>
// <-- render any content you want here
</PageTemplate>

How can I style map items to display in justify-content-around?

I'm looping through products by mapping them and the justify-content-around doesn't apply to them and I'm using bootstrap 4 in my react project .
Here is my code :
{props.products.map((item) => {
if (item.inCart) {
return (
<div className="d-flex justify-content-around w-100" key={item.id}>
<button>remove</button>
<div>
<h5>{item.name}</h5>
</div>
<div>
<h5>{item.price.toLocaleString('ar-EG')}</h5>
</div>
<div>
<h5>{item.number.toLocaleString('ar-EG')}</h5>
</div>
<div>
<h5>{(item.number * item.price).toLocaleString('ar-EG')}</h5>
</div>
<hr />
</div>
);
}
The display flex class applies but not the other one and they all have no margin between them .
How can I make them to display justify-content-around ??
Your problem come from the <hr> tag. I just discovered it by doing this repro on stackblitz. Remove it and it works.
If you readlly need it then just receate it:
const Divider = () => {
return <div className="border-bottom" />;
};
This one is bootstrap dependant but of course you can make it generic easily. You just need to apply it outside of your flex container :
<>
<div className='d-flex justify-content-around' key={item.id}>
<button>remove</button>
<h5>{item.name}</h5>
<h5>{item.name}</h5>
<h5>{item.name}</h5>
</div>
<Divider />
</>;

Does anyone know why all of my elements are being rendered in a single column as if it were a <navbar>?

My component is being rendered in a single column equal to the photo I attached, but it is wrong, it was to be a 5x4 array.
edi1: In an old version of the code I did not have this problem, however I received some props, and since I have to constantly change the contents of the Component, I thought it was good to use state.
render() {
return (
<div className="App">
<Navbar onChange={this.onChange.bind(this)} />
<div className="container mt-10">
<div className="row">
{<RecipeItem list={this.state.searchString} />}
</div>
</div>
</div>
);
}
}
File RecipeItem.js
const RecipeList = ({ searchString }) => {
return(
<div>
<img className="card-img-top img-fluid" src={searchString.thumbnail} alt={searchString.title} />
<div className="card-body">
<h5 className="card-title">{searchString.title}</h5>
<p className="card-text">
<strong>Ingredients: </strong>{searchString.ingredients}
</p>
</div>
</div>
)
}
const RecipeItem = (props) => {
return (
<div className="col-sm-3 mt-4">
<div className="card">
{props.list && props.list.map((searchString, index) =>
<RecipeList searchString={searchString} key={index} />
)}
</div>
</div>
)
}
You're applying col-sm-3 before iterating on each element, you should apply the class on each iteration like this :
const RecipeItem = (props) => {
return (
props.list && props.list.map((searchString, index) =>
<div className="card col-sm-3 mt-4">
<RecipeList searchString={searchString} key={index} />
</div>
)
)
}

Categories