I made such a grid using grid antd . code here.
const { Row, Col } = antd;
const App = () => (
<Row>
<Col className={'first'} span={16}>
<img src="https://picsum.photos/800/400?random=1"/>
</Col>
<Col span={8}>
<Row>
<Col className={'second'} span={24}>
<img src="https://picsum.photos/800/400?random=2"/>
</Col>
<Col className={'third'} span={24}>
<img src="https://picsum.photos/800/400?random=3"/>
</Col>
</Row>
</Col>
</Row>
)
const ComponentDemo = App;
ReactDOM.render(<ComponentDemo />, mountNode);
I'm getting data from the server. There may be more than 3 of them there. I should output the first 3 like this. The rest will be displayed after pressing the button. How can this effect be achieved in myData.map(). To output these elements without using indexes?
I will try do somthing like this
dataSale.slice(0,maxCount).map(({...item},index)=>(
(index===0)?(
<Col key = {index} span={16}>
<SaleCard {...item}/>
</Col>
):(
<Col key={index} span={8}>
<SaleCard {...item}/>
</Col>
)
))
I hope this helps. The following code should work with any number of image links sent by the server. I have mocked with 9 images.
I followed components approach, like what you are supposed to when working with React. I created some components and pieced them back-together to create the design that you wanted to with map().
const { Row, Col, Button } = antd;
const {useState} = React;
const data = [
"https://picsum.photos/800/400?random=1",
"https://picsum.photos/800/400?random=2",
"https://picsum.photos/800/400?random=3",
"https://picsum.photos/800/400?random=4",
"https://picsum.photos/800/400?random=5",
"https://picsum.photos/800/400?random=6",
"https://picsum.photos/800/400?random=7",
"https://picsum.photos/800/400?random=8",
"https://picsum.photos/800/400?random=9",
]
const ColWithImage = (props) => (
<Col span={props.n % 3 == 1 ? 16 : 24}>
<img src={data[props.n-1]}/>
</Col>
)
const MainRow = (props) => {
const k = props.n*3 + 1;
return (
<Row>
<ColWithImage n={k}/>
<Col span={8}>
<Row>
<ColWithImage n={k+1}/>
<ColWithImage n={k+2}/>
</Row>
</Col>
</Row>
)}
const Container = (props) => {
// Create an iterable array depending upon the number of image links
const arr = Array.from(Array(Math.floor(data.length/3)))
// Show only one row if the button is not clicked
// But show all the rows if the button is clicked
return !props.buttonClicked
? <><MainRow n={0}/></>
: (<>
{
arr.map((item, index) => <MainRow key={index} n={index}/>)
}
</>)
}
const App = () => {
const [buttonClicked, setButtonClicked] = useState(false);
const [buttonText, setButtonText ] = useState("Show More");
const handleClick = () => {
setButtonClicked(!buttonClicked);
setButtonText(buttonClicked ? "Show More" : "Show Less");
}
return (<>
<Container buttonClicked={buttonClicked}/>
<Button onClick={handleClick}>{buttonText}</Button>
</>)
}
const ComponentDemo = App;
ReactDOM.render(<ComponentDemo />, mountNode);
You can view the result here.
I created a SalesView component and it will render the layout as per you requirement. It receives an items array of length less than or equal to 3 (Suppose you have total 5 records, only two records will be displayed in second row).
Hope this solution solves your problem.
import { useState } from "react";
import { Row, Col, Button } from "antd";
import "antd/dist/antd.min.css";
const list = Array.from({ length: 20 }).map((_, i) => ({
id: i,
url: `https://picsum.photos/800/400?random=${i + 1}`,
}));
const SalesCard = ({ id, url }) => {
return <img src={url} />;
};
const SalesView = ({ items }) => {
return (
<Row>
{items?.[0] && (
<Col span={16}>
<SalesCard {...items[0]} />
</Col>
)}
{items.length > 2 && (
<Col span={8}>
<Row>
{items?.[1] && (
<Col span={24}>
<SalesCard {...items[1]} />
</Col>
)}
{items?.[2] && (
<Col span={24}>
<SalesCard {...items[2]} />
</Col>
)}
</Row>
</Col>
)}
</Row>
);
};
function App() {
const [showAll, setShowAll] = useState(false);
const totalChunks = Math.ceil(list.length / 3);
const data = Array.from({ length: showAll ? totalChunks : 1 }).map((_, index) => {
const startIndex = index * 3;
const endIndex = startIndex + 3;
return <SalesView key={index} items={list.slice(startIndex, endIndex)} />;
});
const onClick = () => setShowAll(true);
return (
<>
{data}
{!showAll && <Button onClick={onClick}>Show More</Button>}
</>
);
}
export default App;
you can achieve it via CSS or use ternary
dataSale.map((item, index) =>
<Col key={index} span={index < 3 ? 16 : 8}>
<SaleCard {...item}/>
</Col>
)