Render array as a matrix (n items per row) - javascript

I have a view and inside it a map function:
<View style={{width: 500, height: 500}}>
{[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15].map((x,i) => {
return(
<View style={{width: 50, height: 50, backgroundColor: 'red'}}></View>
)
})}
</View>
How can I map this into a pattern? Like 5 on a row?

You can achieve this using flexbox and flexWrap, see the below given example
<View style={{display: "flex"; flexDirection: "row", flexWrap: "wrap", flex: 1;}}>
</View>
You can read this documentation to achieve this
https://reactnative.dev/docs/flexbox

You may split your source array into chunks (rows) of desired length and use nested .map() loops to render rows and cells within them:
const chunkArr = (arr, size) =>
arr.reduceRight((r,i,_,s) => (r.push(s.splice(0,size)),r),[])
Following is a complete live-demo of that concept:
const { useState } = React,
{ render } = ReactDOM,
rootNode = document.getElementById('root')
const cellData = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
const Matrix = ({cells}) => {
const rows = cells.reduceRight((r,i,_,s) => (r.push(s.splice(0,5)),r),[])
return (
<div className="wrapper">
{
rows.map((row,i) => (
<div key={i} className="row">
{
row.map((cell,j) => (
<div key={j} className="cell">
{cell}
</div>
))
}
</div>
))
}
</div>
)
}
render (
<Matrix cells={cellData} />,
rootNode
)
.wrapper {
display: flex;
flex-direction: column;
}
.row {
display: flex;
flex-direction: row;
}
.cell {
width: 20px;
height: 20px;
margin: 5px;
background-color: red;
color: #fff;
text-align: center;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.production.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script><div id="root"></div>

Related

how to get value of zooms in React

Learning React by coding, here i'm using 'react-zoom-pan-pinch' for zoomIn/zoomOut by clicking buttons, but it is also possible to zoomIn and zoomOut using mouse scroll wheel, and i want that value is it possible ? so when i zoomIn or zoomOut using mouse scroll wheel i want that value which shows i have zoomed in or zoomed out and how much.
Demo of code :
https://codesandbox.io/s/qmn69?file=/src/index.js:139-159
code:
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
import styled from "styled-components";
const Container = styled.div`
height: 100vh;
width: 100vw;
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
`;
const Box = styled.div`
width: 50px;
height: 50px;
background-color: ${props => (props.backColor ? props.backColor : "blue")};
margin: 5px;
`;
const Toolbox = styled.div`
display: flex;
justify-content: center;
width: 100%;
max-width: calc(100vw - 60px);
margin-bottom: 10px;
button {
margin-left: 10px;
width: 2em;
}
`;
function App() {
const onClick = () => {
alert("onClick : open popup");
};
const onContextMenu = e => {
e.preventDefault();
alert("onContextMenu : show info");
};
const renderBoxes = () => {
let i;
let arr = [];
for (i = 0; i < 30; i++) {
arr.push(
<Box key={"b" + i} onClick={onClick} onContextMenu={onContextMenu} />
);
arr.push(
<Box
key={"r" + i}
onClick={onClick}
onContextMenu={onContextMenu}
backColor="red"
/>
);
arr.push(
<Box
key={"y" + i}
onClick={onClick}
onContextMenu={onContextMenu}
backColor="yellow"
/>
);
arr.push(
<Box
key={"g" + i}
onClick={onClick}
onContextMenu={onContextMenu}
backColor="gray"
/>
);
}
return arr;
};
return (
<TransformWrapper
defaultScale={1}
defaultPositionX={200}
defaultPositionY={100}
>
{({ zoomIn, zoomOut, resetTransform, positionX, positionY, ...rest }) => (
<React.Fragment>
<Toolbox>
<button onClick={zoomIn}>+</button>
<button onClick={zoomOut}>-</button>
<button onClick={resetTransform}>x</button>
</Toolbox>
<TransformComponent>
<Container>{renderBoxes()}</Container>
</TransformComponent>
</React.Fragment>
)}
</TransformWrapper>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

How to get the background to extend past a parent, overflow container of a certain width

Please see the below code snippet. I have a container with a set width, and in that container, a series of rows who's width is greater than the parent container. I have a background for some of those rows, however, when I scroll to the right to the remaining portion of the rows, the background stops (the background only fills the width of the container). How can I get the background for these rows to persist to the overflow? Thanks.
const Example = () => {
const row = ['John Smith', '2020-10-01', 'jsmith#gmail.com', 'Phoenix', 'Arizona'];
const rows = [row, row, row, row, row];
return (
<div
style={{
background: 'white',
border: '1px solid black',
height: '100%',
margin: '1rem',
overflow: 'auto',
width: '40rem',
}}
>
{rows.map((row: any, index) => (
<div style={{ background: index % 2 === 0 ? 'orange' : 'white', display: 'flex' }}>
{row.map((label: string) => (
<div style={{ margin: '0 5rem', width: '15rem' }}>{label}</div>
))}
</div>
))}
</div>
);
};
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
You have to use two containers if you only want horizontal scroll in table only and apply fit-content to inner container and width(here 40rem) according to wish on outer container
const Example = () => {
const row = ['John Smith', '2020-10-01', 'jsmith#gmail.com', 'Phoenix', 'Arizona'];
const rows = [row, row, row, row, row];
return (
<div
style={{
background: 'white',
border: '1px solid black',
height: '100%',
margin: '1rem',
overflow: 'auto',
width: '40rem',
}}
>
{rows.map((row: any, index) => (
<div style={{ background: index % 2 === 0 ? 'orange' : 'white', display: 'flex',width:'fit-content' }}>
{row.map((label: string) => (
<div style={{ margin: '0 5rem', width: '15rem' }}>{label}</div>
))}
</div>
))}
</div>
);
};
ReactDOM.render(<Example />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
If you say table cells are wider than before than you can solve that out by reducing innermost width(15rem) or some margins (0 5rem)

How to test the state of a functional component in React with Jest (No Enzyme)

Hi everybody how can I test the state of a functional component from the useState hook?
This my component:
const Container = styled.div
display: flex;
flex: 1;
flex-direction: row;
align-items: ${props => props.hasSubtitle ? 'flex-start' : 'center'};
opacity: ${props => props.disabled ? 0.5 : 1.0};
${props => props.style}
const Button = styled.button
padding: 0;
border: none;
background: none;
cursor: pointer;
outline: none;
const TextContainer = styled.div
display: flex;
flex: 1;
flex-direction: column;
margin-left: 12px;
const CheckBox = props => {
const [selected, setSelected] = useState(false);
useEffect(() => {
setSelected(props.selected);
}, [props.selected]);
return (
<Container data-testid={'checkbox'} style={props.style} hasSubtitle={props.subtitle}>
<Button
data-testid={'checkBtn'}
onClick={() => {
if(!props.disabled){
setSelected(!selected);
if(props.onChange) props.onChange(!selected);
}
}}
>
{selected ? <CheckBoxOn/> : <CheckBoxOff/>}
</Button>
<TextContainer>
<Text style={{fontSize: 16}}>
{props.title}
</Text>
{props.subtitle && <Text style={{fontSize: 12}}>{props.subtitle}</Text>}
</TextContainer>
</Container>
);
};
export default CheckBox;
How can I check the value of the state when I render the component with the selected props value to false and when I render it with selected prop to true?
And how I can test if the click event on the button trigger setSelected()? By the way we are not able to use Enzyme
Checking state in your tests lately has been considered a bad practice. What people generally recommend is to check the consequences of a state change: in your case, you could check the presence of CheckBoxOn.

How to get Children width in Reactjs

Here is an online sample https://codesandbox.io/s/jovial-resonance-5mjq0
const Parent = styled.div`
display: flex;
width: 100%;
background: yellow;
justify-content: space-between;
`;
const Children = styled.div`
display: flex;
background: tomato;
height: 50px;
flex: 0 0 10%;
`;
function App() {
return (
<Parent>
<Children />
<Children />
<Children />
<Children />
<Children />
</Parent>
);
}
So regardless the window resizing.
so pure javascript can be done like
document.querySelectorAll(CHILDREN).forEach(e=> {
e.clientWidth
})
but how to get <Children />'s width? I understand it may not common to play DOM in reactjs. But is there a react way to get width? Thanks
Use refs to get DOM elements (after rendering). If you need the width of multiple elements either use several refs and some arithmetic, or use an enveloping parent.
class MyComponent extends React.Component {
constructor() {
super();
this.elementRef = React.createRef();
}
componentDidMount() {
// get the BCR of your ref
const bcr = this.elementRef.current.getBoundingClientRect()
console.log({ width: bcr.width });
}
render() {
return (
<div style={{ width: '234px' }}>
<div ref={this.elementRef} style={{ width: '50%' }}>
Hello, World!
</div>
</div>
);
}
}
ReactDOM.render(<MyComponent />, 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>
<div id="root"></div>

react-select in flex container

How can I make react-select to respect flex layout? Nothing of the below worked.
const Container = styled('div')`
width: 100%;
height: 100%;
display: flex;
flex-flow: row wrap;
justify-content: space-around;
align-items: baseline;
`;
const selectStyles = {
input: base => ({
minWidth: 200,
flex: 1,
<Container>
<Select
style={{ flex: 1 }}
styles={selectStyles}
To make your react-select component flex you need to apply flex:1 props on the container like this:
const styles = {
container: base => ({
...base,
flex: 1
})
};
<Select styles={styles} />

Categories