I have an array like this:
const arr = [1,2,3,4,5,6,7,8,9,10]
And I want to place them as 2 per one line in two dimensional divs. Let me illustrate what im trying to say:
This is main React element:
render() {
return <div className="base">{...}</div>
}
Expected Result:
render() {
return <div className="base">
<div className="container">
<div className="left">
<span>1</span>
<span>2</span>
</div>
<div className="right">
<span>3</div>
<span>4</div>
</div>
</div>
<div className="container">
<div className="left">
<span>5</span>
<span>6</span>
</div>
<div className="right">
<span>7</div>
<span>8</div>
</div>
</div>
<div className="container">
<div className="left">
<span>9</span>
{/* no 10th element because 9 is the last. */}
</div>
{/* no right div because no more elements. */}
</div>
</div>
}
If this was a typical odd even situation, I would do i % 2 here. However, how am i going to close div tag on odd or even? But it is a bit more complicated than that. Is there any way to achieve this in React? I'm using TypeScript by the way and latest ReactJS.
In order to render more advanced loops in react, you need to get used to chunking your arrays. you can simply chunk the array twice using the following function, then you can map this array recursively to render your desired output:
function chunk_array(arr,chunkSize=2) {
const result=[];
for(let i=0;i<arr.length;i+=chunkSize) {
result.push(arr.slice(i,i+chunkSize));
}
return result;
}
**NOTE: I made a JS fiddle so you can visualize how this array changes to become the shape we need to render your desired html output ** JS FIDDLE
now you can utilize this in render to accomplish what you want.
import React from 'react';
function chunk_array(arr,chunkSize=2) {
const result=[];
for(let i=0;i<arr.length;i+=chunkSize) {
result.push(arr.slice(i,i+chunkSize));
}
return result;
}
const arr = [1,2,3,4,5,6,7,8,9,10];
const chunked = chunk_array(chunk_array(arr));// we chunk array twice to get desired structure.
class Example extends Component {
render() {
return (
<div className="container">
{chunked.map((container,i)=>(
<div className="base" key={i}>
{container.map((row,i2)=>(
<div key={i2} className={(i2===0?"left":"right")}>
{row.map((item,i3)=><span key={i3}>{item}</span>)}
</div>))}
</div>))}
</div>
)
}
}
This can be done in some ways but here is a sample: https://codesandbox.io/s/distracted-joliot-lkdxq
import React from "react";
import "./styles.css";
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const Result = () => {
return (arr.map(item => {
return (
<div key={item} className="box">
{item}
</div>
);
}));
};
export default function App() {
return (
<div className="App">
<Result />
</div>
);
}
Here is the css:
.App {
display: grid;
grid-template-columns: 50px 50px;
grid-gap: 10px;
}
.box {
display: flex;
border: 1px black solid;
width: 50px;
height: 50px;
align-items: center;
justify-content: center;
}
I think this is the answer you are looking for:
https://codesandbox.io/s/goofy-snowflake-tdzjn?file=/src/App.js
import React from "react";
import "./styles.css";
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const Result = () => {
return arr.map((item, index) => {
return (
index % 2 === 0 && (
<div key={item} className="box">
<span>{arr[index]}</span>
<span>{arr[index + 1]}</span>
</div>
)
);
});
};
export default function App() {
return (
<div className="App">
<Result />
</div>
);
}
Here is the css:
.App {
display: grid;
grid-template-columns: 50px 50px;
grid-gap: 10px;
}
.box {
display: flex;
border: 1px black solid;
width: 50px;
height: 50px;
align-items: center;
justify-content: center;
}
.box span {
margin: 0 5px;
}
You could use bootstrap to do this. Put the everything inside a div className="row" and then have each of the items have className="col-6". Bootstrap cuts every row into 12 columns, so giving each element 6 of those columns will cause them to be 2 on a line as you want. You'll need to npm install bootstrap and include the appropriate script tags in your application. Take a look here, https://getbootstrap.com/docs/3.3/getting-started/. Let me know if this helps!
Related
I'm new to react and i hope someone can help me with this. I've searched everywhere for a solution to my problem with no luck.
Basically i want to render an array of SVG images inside a div as a backgroundImage: url().
I've managed to render my array with math.random but i want the SVG images to render in same order as in the array.
This is my code so far:
import './ListView.css';
import Green from '../Assets/ListCard/Green.svg';
import Brown from '../Assets/ListCard/Brown.svg';
import Orange from '../Assets/ListCard/Orange.svg';
import Mail from '../Assets/Icons/Mail.svg'
import Phone from '../Assets/Icons/Phone.svg'
function ListView({ userData}) {
const cardImages = [Green, Brown, Orange]; /// Array
const renderList = cardImages.map(function(image) { /// Tried to map through the array with -
return image; /// no luck
})
/// This Math.radom method works, but not the solution i want
const randomItem = cardImages[Math.floor(Math.random()*cardImages.length)];
return ( /// Below inside the div is where i want to render the images.
<div className="list-card" style={{backgroundImage: `url(${renderList})`}}>
<div className="list-card-wrapper">
<div className="list-user-image"><img src={userData.picture.medium} alt=""/></div>
<div className="list-user-info">
<div className="list-user-name">{userData.name.first} {userData.name.last}</div>
<div className="list-user-location">{userData.location.city}</div>
</div>
<div className="list-user-contact">
<img height={19} src={Mail} alt="svg"/>
<img height={19} src={Phone} alt="svg"/>
</div>
</div>
</div>
)
}
export default ListView```
you will need import image and bind it like below:
import logo from './logo.svg';
function App() {
return (
<div className="App">
<img src={logo} className="App-logo" alt="logo" />
</div>
);
}
export default App;
This is what you might be looking for:
import "./styles.css";
export default function App() {
const items = [
{ name: "first" },
{ name: "second" },
{ name: "third" },
{ name: "fourth" },
{ name: "fifth" },
{ name: "sixth" }
];
const colorArray = ["green", "brown", "orange"];
return (
<div className="App">
{items.map((item, index) => {
const classColorIndex = index % 3;
return (
<div
className={`list-card ${colorArray[classColorIndex]}`}
key={index}
>
<p>{item.name}</p>
</div>
);
})}
</div>
);
}
The main concept behind this is, that you have to focus on the index of the item and check if it the first, second, or third item (I am considering it 3 because you have 3 colors in the array). Now, according to index number, you need to add a class to that div, and using CSS, you could provide background to each div according to that array.
In this sample, I have used plain background color, but I have commented how you could use svg as well. on APP.css, and here is the css
.App {
font-family: sans-serif;
text-align: center;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.list-card {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
flex-basis: 50%;
}
.list-card.green {
background: green;
/* background:url('../../Green.svg'); */
}
.list-card.brown {
background: brown;
}
.list-card.orange {
background: orange;
}
and here is the sandbox link:
https://codesandbox.io/s/stack-overflos-sample-z0yxyk?file=/src/App.js
On this example, you can see background is assigned, exactly to the array.
I am trying to have my React components that are created based on user input stacked like this:
|Component|
|Component|
|Component|
|Component|
|Component|
I want them to to be in the middle of the page, and stacked on on top of the other. However, they are currently ending up on the left side stacked like that.
This is my CSS code:
.ingredients-input-bar {
display: flex;
background-color: rgb(71, 79, 105);
justify-content: center;
width: 400px;
}
This is the code for the input bar:
return (
<div className='ingredients-input-bar'>
<form>
<input
type='number'
id='quantity'
value={quantity}
onChange={getVariables}
/>
</form>
<h3>New Quantity: {fractionalize( ( (props.newServings / props.originalServings) * quantity) )}</h3>
</div>
And this code builds all of the input bars:
export const IngredientsInput = (props) => {
let inputBars = [];
for (let i = 0; i < props.numIngredients; i++) {
inputBars.push(
<IngredientsInputBar
newServings={props.newServings}
originalServings={props.originalServings} />);
}
return inputBars;
First of all you shouldn't render elements like that. You should use .map function in react. Here you can read more about it.
This should work.
const numIngredients = new Array(5).fill("");
This line just creates and array of empty strings depending on a number. In your code it will be props.numIngredients
const numIngredients = new Array(5).fill("");
return (
<div
style={{
display: "flex",
margin: "auto",
flexDirection: "column",
width: "400px"
}}
>
{numIngredients.map(() => (
<div style={{ display: "flex" }}>One div</div>
))}
</div>
);
I created working example for you with flex - https://codesandbox.io/s/react-functional-component-forked-k1owj?file=/src/index.js
Hello I have this code using React.js :
import React, { Component } from 'react';
import Select from "./components/Select/Select";
import Switch from "./components/Switch/Switch";
class App extends Component {
state = {
Test : [
{value : "0", name : "1"},
]
}
render() {
return (
<>
<div className="form-inline">
<div className="col-sm-9">
<Select list={[...this.state.Test]}/>
<Switch />
</div>
</div>
</>
);
}
}
where Select.js :
import React from "react";
const selectoption = ({ list }) => (
<select className="custom-select">{list.map(option => (<option key={option.value} value={option.value}>{option.name}</option>))}
</select>
);
export default selectoption;
And the last file Switch.js :
import React from "react";
const switchoption = () => (<div className="custom-control custom-switch">
<input type="checkbox" className="custom-control-input" id="customSwitch1" />
<label className="custom-control-label" htmlFor="customSwitch1">Slot/Map</label>
</div>);
export default switchoption;
But the problem is that I don't have select next to the switch like I want.
[![My pic][1]][1]
Thank you very much !
[1]: https://i.stack.imgur.com/CSlRi.png
You can use flexbox here. Similar to the code shown below. In case of React use className instead of class. Wrap the divs that should be next to each other in a parent class which has flex-direction of type row and each of the child classes should have flex-direction of type column. It is very similar to a table row layout.
This link is very helpful: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.parent {
display: flex;
flex-direction: row
width: 100%;
}
.child {
display: flex;
flex-direction: column;
}
<div class="parent">
<div class="child">Child 1</div>
<div class="child">Child 2</div>
</div>
you just need to wrappe them both in flex container
class App extends Component {
state = {
Test : [
{value : "0", name : "1"},
]
}
render() {
return (
<>
<div className="form-inline">
<div className="flex">
<Select list={[...this.state.Test]}/>
<Switch />
< /div>
</div>
</>
);
}
}
in css
.flex{
display:flex;
width:100% ;
justify-content:space-between;
align-items:center;
}
.flex select {
flex:1;
display:inline;
}
I have a problem on which I cannot find a simple solution. So this is my Header:
const Header = ({ title }) => {
return (
<div className={styles.Header}>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</div>
);
};
How can I apply custom styles with styled-components for h1 and button elements? I tried
const CustomHeader = styled(Header)`
${h1} ${button}
`;
const h1 = styled(h1)`
max-width: 500px
`
const button = styled(button)`
padding-left: 100px
`
but this is not working, I get an error in terminal.
I also tried this:
return (
<CustomHeader>
<div className={styles.Header}>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</div>
</CustomHeader>
);
};
const CustomHeader = styled(Header)`
h1 {
max-width: 500px;
}
button {
padding-left: 100px;
}
`;
Any help will be appreciated.
First you need to define styled component in your React function and create a wrapper like following:
// added demo css here for h1 tag, you can add your own
const CustomHeader = styled.div`
h1 {
font-family: Poppins;
font-size: 14px;
font-weight: 600;
font-stretch: normal;
font-style: normal;
line-height: 1.5;
letter-spacing: 0.02px;
text-align: left;
color: #0f173a;
}
`;
Then wrap your return inside the CustomHeader wrapper.
const Header = ({ title }) => {
return (
<CustomHeader>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</CustomHeader>
);
};
You can add any tag inside CustomHeader that you want to customize.
You're almost there.
Its not working because you are setting className directly on div element of your Header component.
According to the styled-component documentation:
The styled method works perfectly on all of your own or any third-party components, as long as they attach the passed className prop to a DOM element.
https://styled-components.com/docs/basics#styling-any-component
So, in your case you need to:
const Header = ({ title, className }) => {
return (
<div className={className}>
<h1>{title}</h1>
<button>EXIT</button>
</div>
);
};
const CustomHeader = window.styled(Header)`
h1 {
max-width: 500px;
}
button {
padding-left: 100px;
}
`;
const App = () => {
return (
<React.Fragment>
<Header className='' title={"title"} />
<CustomHeader title={"title"} />
</React.Fragment>
);
};
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="//unpkg.com/styled-components#4.0.1/dist/styled-components.min.js"></script>
<div id="root"></div>
So, i set Header like this:
const Header = ({ title, className }) => {
return (
<div className={className}>
And where i did <Header className='' title={"title"} /> you can do like this:
<Header className={styles.Header} title={"title"} />
// Code
const Header = ({ title }) => {
return (
<Header>
<h1>{title}</h1>
<button>
{EXIT}
</button>
</Header>
);
};
// Styles
const Header = styled.div`
h1{
styles...
}
button{
styles...
}
`;
Whats my requirement: i have some images in my external folder and i need to import to component and display it and also have to use Virtual Scroll here i have to display 1 row in div and in that 1 row have to show 5-6 images
What i did : i consumed images using context from external folder and showed images in 1 rows in div and 5-6 images but i am facing issue unable to set it to Virtual scrolling
as i checked react-virtualized & react-window plugin but i am not sure how my data is used in that format
After using the react-tiny-virtual-list images are getting stacked
below is my code
class App extends React.Component{
state={
Response:[],
}
importAll(r) {
return r.keys().map(r);
}
componentWillMount() {
let data = this.importAll(require.context('./imageFolder/', false, /\.(png|jpe?g|svg)$/));
this.setState({ Response:data})
}
render(){
return(
<div className="container" id="imagecontainer">
<div className="viewport">
{this.state.Response.map((image, index) => <img key={index} src={image} alt="info"></img> )} }
</div>
</div>
)
}
.container {
padding: 0% 6%;
height: 400px;
}
.viewport {
height: -webkit-fill-available;
width: 100%;
border: 1px solid black;
overflow: scroll;
}
img {
height: 250px;
width: 150px;
padding: 35px;
}
After implementing React-tiny-list
<div id="container">
<div id="viewport">
<VirtualList
height='400px'
width='100%'
itemCount={this.state.items.length}
itemSize={20} // Also supports variable heights (array or function getter)
style={{padding:'20px'}}
renderItem={({index, style}) =>
<div key={index} style={style}>
<img key={index} src={this.state.items[index]} alt="info"></img>
</div>
}
/>
</div>
</div>
you can also use the https://github.com/bvaughn/react-virtualized plugin in this if you want to display this as table you can choose list or you can choose grid also .For you requirement i recommend using Masonry from 'react-virtualized';
below is the sample for displaying
import React from 'react';
import {
CellMeasurer,
CellMeasurerCache,
createMasonryCellPositioner,
Masonry
} from 'react-virtualized';
import 'react-virtualized/styles.css';
var images = [];
const columnWidth = 250;
const defaultHeight = 260;
const defaultWidth = columnWidth;
const cache = new CellMeasurerCache({
defaultHeight,
defaultWidth,
fixedWidth: true
})
// Our masonry layout will use 3 columns with a 10px gutter between
const cellPositioner = createMasonryCellPositioner({
cellMeasurerCache: cache,
columnCount: 4,
columnWidth,
spacer: 27
})
function cellRenderer ({ index, key, parent, style }) {
const datum = images[index]
const height = columnWidth || defaultHeight ;
return (
<CellMeasurer
cache={cache}
index={index}
key={key}
parent={parent}
>
<div style={style}>
<img
src={datum}
style={{
height: height,
width: columnWidth,
display: "block"
}}
alt="info"
/>
</div>
</CellMeasurer>
)
}
class Grid extends React.Component{
importAll(r) {
return r.keys().map(r);
}
componentWillMount() {
images = this.importAll(require.context('../imageFolder/', false, /\.(png|jpe?g|svg)$/));
}
render(){
return(
<div id="container">
<div id="viewport">
<Masonry
cellCount={images.length}
cellMeasurerCache={cache}
cellPositioner={cellPositioner}
cellRenderer={cellRenderer}
height={400}
width={1320}
/>
</div>
</div>
)
}
}
export default Grid;
I hope this will resolve your issue
If you're having trouble implementing the virtual scroll, note that the order of the imports is important when doing this, so pay heed to this - it could be contributing to your issue. (An aside: There is an npm plugin for implementing a virtual list.)
An overview of the import order for virtual scroll is:
import * as React from 'react';
import Paper from '#material-ui/core/Paper';
import {
Grid,
VirtualTable,
TableHeaderRow,
} [from material ui];
import {
your-components
} from 'your-path';
(above is non-specific, just a rough guide to the order)
You could also use a ScrollView if you are unable to implement a "Virtual scroll".
The following style will give you a horizontal scroll (as opposed to the default vertical), to enable you to display your images in a horizontally-scrollable row
<ScrollView horizontal={true}>
Hope this helps