I'm wondering what is the best approach to implement layouting in React app.
Let's say we want to have 4 components laid out in simple grid. The most basic way would be something like this.
<svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}> <A color="red" x={0} y={0} width={width/2} height={height/2} /> <B color="blue" x={width/2} y={0} width={width/2} height={height/2} /> <B color="green" x={0} y={height/2} width={width/2} height={height/2} /> <A color="yellow" x={width/2} y={height/2} width={width/2} height={height/2} /> </svg>
http://codepen.io/anon/pen/OWOXvV?editors=0010
It will work fine, but typing explicit size values is error-prone and not dev-friendly. What if we could use percentage values (0 - 1) instead?
const Container = ({x, y, width, height, children}) => { return ( <g transform={`translate(${x}, ${y})`}> {React.Children.map(children, (child) => React.cloneElement(child, { // this creates a copy x: child.props.x * width, y: child.props.y * height, width: child.props.width * width, height: child.props.height * height }))} </g> ); }; <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}> <Container width={width} height={height}>{/* one root container is given real pixel size */} <Container width={1/2}>{/* it's children recursively use 0-1 coordinates */} <A color="red" height={1/2} /> <B color="green" y={1/2} height={1/2} /> </Container> <Container x={1/2} width={1/2}> <B color="blue" height={1/2} /> <A color="yellow" y={1/2} height={1/2} /> </Container> </Container> </svg>
http://codepen.io/anon/pen/PWEmVd?editors=0010
In this case we'll allow Container component to map it's children relative values to real pixel values. It's much easier to use.
Another step would be to create layout container, f.e. HContainer that simply lays its children horizontally.
const HContainer = ({ x, y, width, height, children }) => { const c = React.Children.toArray(children); const ratio = width / c.reduce((sum, child) => (sum + child.props.width), 0); return ( <g transform={`translate(${x}, ${y})`}> {c.reduce((result, child) => { const width = child.props.width * ratio; result.children.push(React.cloneElement(child, { // this creates a copy x: result.x, y: 0, width, height })); result.x += width; return result; }, { x: 0, children: [] }).children} </g> ); }; <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}> <HContainer width={width} height={height}>{/* one root container is given real pixel size */} <Container width={1/4}>{/* it's children recursively use 0-1 coordinates */} <A color="red" height={1/2} /> <B color="green" y={1/2} height={1/2} /> </Container> <VContainer width={3/4}> <B color="blue" /> <A color="yellow" /> <HContainer height={1/2}> <B color="pink" /> <A color="violet" width={3} /> <B color="#333" /> </HContainer> </VContainer> </HContainer> </svg>
http://codepen.io/anon/pen/pRpwBe?editors=0010
Let's say we'd like some components be removed when width or height is below some value. You'd probably use conditional rendering like this.
const MinWidth = ({ children, width, minWidth, ... others }) => { return minWidth > width ? null : <Container width={width} {... others }>{ children }</Container>; }; <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`}> <HContainer width={width} height={height}>{/* one root container is given real pixel size */} <Container width={1/4}>{/* it's children recursively use 0-1 coordinates */} <A color="red" height={1/2} /> <B color="green" y={1/2} height={1/2} /> </Container> <VContainer width={3/4}> <B color="blue" /> <MinHeight height={1} minHeight={80}> <A color="yellow" /> </MinHeight> <HContainer height={1/2}> <B color="pink" /> <A color="violet" width={3} /> <MinWidth width={1} minWidth={60}> <B color="#333" /> </MinWidth> </HContainer> </VContainer> </HContainer> </svg>
http://codepen.io/anon/pen/dNJZGd?editors=0010
But this leaves empty spaces where skipped components used to be. Layout containers should be able to expand rendered components to fill available space.
And here's the tricky part. I can see no other way to see if component will render, but to instantiate and render it (and it's children). Then, if I lay 3 child components within avaialable space and discover that 4th should not be rendered I'll have to re-render previous 3. It feels like breaking React flow.
Does anyone have any ideas?
The entire goal of this article was to make it clear that you are not required to use CSS-in-JS with React, that React works with plain CSS just fine.
Getting started with react-responsive First, begin by creating a new React project with no dependencies. We'll perform an npm install of the react-responsive package with npm i -S react-responsive . Just so you know, react-responsive anticipates different use cases, so we can use it with Hooks or with components.
React-responsive is a media query module that provides CSS media queries in react as a component or hook for responsive web design. This is super useful for rendering or removing specific styled elements in the DOM — restructure your DOM in terms of CSS/Sass Styling, depending on the screen resolution/size.
Use flexbox in inline styles. You are already using inline style from the look of your code. Here is some help
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With