React JS element width same as its height - html

I am new to React JS. Now struggled with a little thing that I need to set an element width equal to its height. We can manage with in jQuery something like below:
var divWidth = $('.main').width();
$('.main').height(divWidth);
$( window ).resize(function() {
var divWidth = $('.main').width();
$('.main').height(divWidth);
});
.container {
width: 100%;
max-width: 400px;
}
.main {
width: 100%;
background: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="container">
<diV class="main">
test
</diV>
</div>
How can we do like this in React JS?

You can use the jquery window listener to pass props to a component and set it style. It will have the same effect.
import React, { Fragment, useState, useEffect } from "react";
import ReactDOM from "react-dom";
function LiveVisitors() {
const [dimensions, setDimensions] = useState({
x: document.body.clientWidth,
y: document.body.clientHeight
});
window.addEventListener("resize", () => {
setDimensions({
x: document.body.clientWidth,
y: document.body.clientHeight
});
});
let fraction = dimensions.x / 10;
return (
<div
style={{
border: "1px solid red",
width: fraction,
height: fraction
}}
>
{JSON.stringify(dimensions)}
</div>
);
}
const wrapper = document.getElementById("container");
ReactDOM.render(<LiveVisitors />, wrapper);
You can modify this playground: https://codesandbox.io/s/react-playground-forked-v66j1?file=/index.js:0-719

Related

Styled-components: Style not updated after switching from mobile

Here:
Open the app in desktop width, notice the div has green background
Reduce browser width to mobile, the div background should change to gray
Again, increase browser width to desktop, notice the gray background remains, instead of green
What should have happened
The background in last step should be green as in the first step, isn't it?
Logging value of isMobile does seem to show it is being updated.
Here is also code:
import React from 'react';
import styled from 'styled-components';
import { useMediaQuery } from 'react-responsive';
let MenuItem = styled.div`
height: 100px;
width: 100px;
border:1px solid red;
background-color: green;
// Select those items which are children of .submenu
.submenu & {
background-color: ${({ isMobile }) => {
return isMobile && 'lightgray';
}};
}
`;
function App() {
const isMobile = useMediaQuery({ query: '(max-width: 524px)' });
return (
<div>
<div className="submenu">
<MenuItem isMobile={isMobile}>test</MenuItem>
</div>
</div>
);
}
export default App;
import React, {useEffect, useState} from 'react';
import styled from 'styled-components';
import {useMediaQuery} from 'react-responsive';
let MenuItem = styled.div`
height: 100px;
width: 100px;
border:1px solid red;
background-color: green;
`;
function App() {
const isMobile = useMediaQuery({query: '(max-width: 524px)'});
const [color, setColor] = useState('green');
useEffect(() => {
if (isMobile) setColor('silver');
else setColor('green');
}, [isMobile])
return (
<div>
<div className="submenu">
<MenuItem style={{background: color}} isMobile={isMobile}>test</MenuItem>
</div>
</div>
);
}
export default App;
You could re-write this as:
const MenuItem = styled.div`
height: 100px;
width: 100px;
border:1px solid red;
background-color: green;
`;
const SubMenu = styled.div`
${MenuItem} {
background-color: ${({ isMobile }) => (isMobile ? `red` : 'lightgray')};
}
`;
function App() {
const isMobile = useMediaQuery({ query: '(max-width: 524px)' });
return (
<>
<SubMenu isMobile={isMobile}>
<MenuItem>MenuItem in SubMenu</MenuItem>
</SubMenu>
<MenuItem>MenuItem</MenuItem>
</>
);
}
Stackblitz
It is the correct answer:
https://stackblitz.com/edit/react-t7gqwx?file=src%2FApp.js,src%2Findex.js
You shouldn't use .submenu &.

Render raw HTML inside a react div

I have this raw HTML that is stored in the database and I'm trying to render it inside a div.
const style = {
border: '2px solid #eee',
height: '270px',
width: '100%',
overflow: 'auto',
padding: '10px'
}
const test = () => {
const [contentFromDB, setContentFromDB] = useState("");
useEffect(() => {
async function fetchData() {
setContentFromDB(await myAPI.getData())
}
}, []);
return (
<>
<div className="row">
<h3>Test Render</h3>
<div style={style}>
{contentFromDB}
</div>
</div>
</>
)
}
export default test;
The problem is that it is keeping all the HTML tags, it is rendering as a string (image below). Is there a way to render the raw HTML inside my div?
You can use dangerouslySetInnerHTML to achieve this.
const style = {
border: '2px solid #eee',
height: '270px',
width: '100%',
overflow: 'auto',
padding: '10px'
}
const test = () => {
const [contentFromDB, setContentFromDB] = useState("");
useEffect(() => {
async function fetchData() {
setContentFromDB(await myAPI.getData())
}
}, []);
return (
<>
<div className="row">
<h3>Test Render</h3>
<div style={style}>
<div dangerouslySetInnerHTML={{__html:contentFromDB}} />
</div>
</div>
</>
)
}
export default test;

How to resize the images to fit in fixed size div?

I am working on project(social media web app), where user has permission to upload variety of media. I will explain problem with example, let's say I have div of 500px300px and I am getting images of various dimensions, it could be portrait or landscape or could be small images like 50px50px. I want to fit such image in fixed size div, without losing its aspect ratio or without getting it cropped or without getting stretched. I tried with css properties but none of them seems to work fine with all type images, I am struggling to find solution for this.
Component to render image:
import React, { useRef } from "react";
export default function Example(props) {
const myRef = useRef(null);
const [dimensionofImg, setDimensionofImg] = React.useState(null);
const [dimensionsofDiv, setDimensionsofDiv] = React.useState(null);
const [imagedimensions, setImagedimensions] = React.useState(null);
React.useEffect(() => {
setDimensionsofDiv({
width: myRef.current.offsetWidth,
height: myRef.current.offsetHeight
});
}, []);
React.useEffect(() => {
let dimensionTocompare;
if (
dimensionofImg &&
dimensionofImg.width < dimensionofImg &&
dimensionofImg.height
) {
dimensionTocompare = dimensionsofDiv.width;
let changedWidth =
(dimensionTocompare * dimensionofImg.width) / dimensionofImg.height;
setImagedimensions({
maxWidth: "",
maxHeight: "100%",
width: changedWidth,
height: ""
});
} else if (
dimensionofImg &&
dimensionofImg.width > dimensionofImg &&
dimensionofImg.height
) {
dimensionTocompare = dimensionsofDiv.height;
let changedHeight =
(dimensionTocompare * dimensionofImg.height) / dimensionofImg.width;
setImagedimensions({
maxWidth: "100%",
maxHeight: "",
width: "",
height: changedHeight
});
}
else if (
dimensionofImg && dimensionofImg.width == dimensionofImg && dimensionofImg.height
) {
setImagedimensions({
maxWidth: "100%",
maxHeight: "100%",
width: "",
height: ""
});
}
}, [dimensionofImg, dimensionsofDiv]);
function renderContent() {
return (
<div>
width of div: {dimensionsofDiv.width}
<br />
height of div: {dimensionsofDiv.height}
</div>
);
}
return (
<div>
{dimensionsofDiv && renderContent()}
dimensions of image width{dimensionofImg && dimensionofImg.width}, height
{dimensionofImg && dimensionofImg.height}
<div
style={{ height: 500, width: 300, border: "solid 1px red" }}
ref={myRef}
>
<img
style={{
maxWidth: `${imagedimensions && imagedimensions.maxWidth}`,
maxHeight: `${imagedimensions && imagedimensions.maxHeight}`,
width: `${imagedimensions && imagedimensions.width}`,
height: `${imagedimensions && imagedimensions.height}`
}}
onLoad={(e) => {
setDimensionofImg({
width: e.currentTarget.offsetWidth,
height: e.currentTarget.offsetHeight
});
}}
alt=""
src={props.src}
/>
</div>
</div>
);
}
import "./styles.css";
import Example from "./component"
const src = "https://picsum.photos/100/800/?random";
export default function App() {
return (
<div className="App">
<Example src={src}/>
</div>
);
}
The most closest thing to what you need is object-fit: contain property.
This will fill the div depending whether it is landscape (will take all the width) or portrait (will take all of the height), and all this maintaining the aspect ratio. You just need to provide dimensions for div.
div {
width: 500px;
height: 500px;
}
img {
width: 100%;
height: 100%;
object-fit: contain;
}
Restrict the width to your div width and leave the height as auto to maintain ratio.
.container { width: 500px }
.container img { max-width: 100%; height : auto }

Child component is higher than it's parent div

I'm starting to work with react and have to build a clock component.
I want my parent div to have the same height as a child component. Why doesn't child height affect it's parent height?
HTML:
import React, { useState, useEffect } from "react";
import "./clock.scss";
export const Clock = () => {
let [date, setDate] = useState(new Date());
useEffect(() => {
let timer = setInterval(() => setDate(new Date()), 1000);
return function cleanup() {
clearInterval(timer);
};
});
return (
<div className="clock-wrapper">
<span className="test">
{date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}
</span>
</div>
);
};
export default Clock;
SCSS (other components don't have css yet). Class "test" - green container. Class "clock-wrapper" - red container.
.dashboard {
display: flex;
justify-content: space-between;
padding: 25px 40px 25px 40px;
}
.clock-wrapper {
$_size-100: 100px;
}
.test {
color: $color-pickled-bluewood;
font-size: $_size-100;
font-weight: bold;
}
Image with current result. Red border is parent size. Green border with background color is children component.
Thanks for your help.

Is there a good way to implement a div cross which expands onHover?

I need to display a cross in react like this and each div needs to expand onHover.
It should push the other divs away or make them smaller. Does somebody know a good strategy to achieve this either with CSS or React conditional classNames?
I can only achieve on of those: The cross or the expansion and pushing away of the other divs but without the cross form.
I tired:
text-align: -webkit-center;
with
float: left;
there are tons of way to implement it. Take a look at my snippet:
https://stackblitz.com/edit/react-opu88z
JS
import React, { Component } from 'react';
import { render } from 'react-dom';
import Hello from './Hello';
import './style.css';
class App extends Component {
constructor() {
super();
this.state = {
hoveringEl: 1,
};
}
getWidth = (n) => {
if(this.state.hoveringEl === n){
return 70
} else {
return 10
}
}
hover = (n) => this.setState({ hoveringEl: n })
render() {
return (
<div className="container">
<div
style={{ backgroundColor: 'red', width: `${this.getWidth(1)}%` }}
onMouseEnter={() => this.hover(1)}
/>
<div
style={{ backgroundColor: 'green', width: `${this.getWidth(2)}%` }}
onMouseEnter={() => this.hover(2)}
/>
<div
style={{ backgroundColor: 'yellow', width: `${this.getWidth(3)}%` }}
onMouseEnter={() => this.hover(3)}
/>
<div
style={{ backgroundColor: 'blue', width: `${this.getWidth(4)}%` }}
onMouseEnter={() => this.hover(4)}
/>
</div>
);
}
}
render(<App />, document.getElementById('root'));
CSS
div.container {
width: 100%;
min-height: 50px;
}
div.container > div{
height: 50px;
float: left;
}