How to update the state in different mobile screens using React Hooks - reactjs

I am working on React project, In that I have a button under that I have another div, I written a function if My screen width is 320px then margin-bottom: 150px has to apply under button. it is working fine, but when I am in 320px screen if I click the button then under button margin-bottom: 150px is applied. Here the problem comes now when I go to 375 px here also margin-bottom: 150 px applied automatically. so someone help to how to update state in 375px. Because in 375px screen I have to apply margin-bottom: 300 px.
If you have any questions please let me know thank you.
This is My code
This is App.js
import React, { useState, useLayoutEffect } from 'react';
import './App.css';
const App = () => {
const [style, setStyle] = useState(null)
function useMediaQuery() {
const [screenSize, setScreenSize] = useState([0]);
useLayoutEffect(() => {
function updateScreenSize() {
setScreenSize([window.innerWidth]);
}
window.addEventListener("resize", updateScreenSize);
updateScreenSize();
return () => window.removeEventListener("resize", updateScreenSize);
}, []);
return screenSize;
}
const [mediaQuery] = useMediaQuery();
console.log(mediaQuery, '***')
const applyStyle = () => {
if(mediaQuery === 320) {
setStyle({
marginBottom: '150px'
})
}
}
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
<div className='first'>
<button onClick={applyStyle} style={style} className='btn btn-primary'>Click here</button>
<span className='closeWindow'><i className="far fa-window-close"></i></span>
</div>
<div className='second'>
</div>
</div>
</div>
</div>
)
}
export default App

in App.css write a #media query:
#media screen and (max-width: 375px) {
button {
margin-bottom: 300px;
}
}

You can apply media queries in React either programmatically, or using css.
Option 1, using css:
.myButton{
/* media queries */
#media (max-width: 320px) {
margin-bottom: 150px;
}
#media (max-width: 375px) {
margin-bottom: 300px;
}
}
and then:
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
<div className='first'>
<button onClick={applyStyle} className='myButton btn btn-primary'>Click here</button>
<span className='closeWindow'><i className="far fa-window-close"></i></span>
</div>
<div className='second'>
</div>
</div>
</div>
</div>
)
Option 2, programmatically:
import React, { useState, useEffect, useLayoutEffect } from 'react';
import './App.css';
const App = () => {
const [mediaMatch, setMediaMatch] = useState();
const handler = e => setMediaMatch(e.matches);
useEffect(() => {
window.matchMedia('(min-width: 768px)').addListener(handler);
return () => {
window.removeEventListener(handler);
};
}, []);
return (
<div className="container">
<div className="row">
<div className="col-12">
<div className="first">
<button
onClick={applyStyle}
style={{
marginBottom: mediaMatch ? '300px' : '150px'
}}
className="btn btn-primary"
>
Click here
</button>
<span className="closeWindow">
<i className="far fa-window-close" />
</span>
</div>
<div className="second" />
</div>
</div>
</div>
);
};

Related

How to change the react-bootsrap-range-slider bar color?

I use React.js library "react-bootstrap-range-slider" but
I can't figure out how to change bar color like following photo.
MyPage.js
const MyPage = () => {
const [ value, setValue ] = React.useState(50);
return (
<div className="container">
<div className="row mx-auto text-center">
<RangeSlider
value={value}
onChange={e => setValue(Number(e.target.value))}
/>
<Link to={`/`} className='btn btn-primary col-4'>Back</Link
</div>
</div>
);
}
export default MyPage;
App.css
input[type="range"]::-webkit-slider-thumb {
background: white !important;
}
/* All the same stuff for Firefox */
input[type="range"]::-moz-range-thumb {
background: white !important;
}
/* All the same stuff for IE */
input[type="range"]::-ms-thumb {
background: white !important;
}

How can i hover in React using useState

I wanna toggle a class when hovering on a Container by changing the opacity from 0 to 1, I've used onmouseEnter and onMouseLeave Event to toggle the class, but when I console hover state I see that is changing from true to false when I hover but the class "Show" is not changing.
What do you think ?
<--Components-->
import React,{useState} from 'react';
import './MyWork.css';
import {Visibility, GitHub } from "#material-ui/icons";
const SingleProject = ({src, title}) => {
const [hover, isHover] = useState(false);
const showIcons = isHover ? "Show" : "";
return (
<div className="card-container" onMouseEnter={()=> isHover(true)} onMouseLeave={()=> isHover(false)}>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${showIcons}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;
<--- Css--->
.card-container {
height: 314px;
width: 500px;
cursor: pointer;
position : relative;
}
.Info {
position: absolute;
height: 100%;
width: 100%;
top:0;
left:0;
display:flex;
justify-content:center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
}
.Info.Show {
opacity: 1;
}
When assigning the value to showIcons, you need to use hover instead of isHover which is the setter function for that state.
Additionally, I recommend naming the setter function setHover to avoid confusion and be more semantic. You can also add conditional Show class like this, which is more concise:
iconst SingleProject = ({src, title}) => {
const [hover, setHover] = useState(false);
return (
<div
className="card-container"
onMouseEnter={()=> setHover(true)}
onMouseLeave={()=> setHover(false)}
>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${hover ? "Show" : ""}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;
You are using the setter instead of the state itself on your condition. Change isHover with hover like below:
const showIcons = hover ? "Show" : "";

Problems with Styled-Components conditional style rendering. I'm not sure what's wrong

I'm trying to toggle a hamburger menu on and off. I've console logged to check that the boolean values are changing, but the css isn't.
My issue is with 'props.active?' it's working but the '.mobile-menu' class is not changing. I'm not entirely sure what I need to do to get it to work. I've tried to make changes to the style I want to affect because I thought maybe you can't toggle as display, however,f visibility and opacity still aren't changing either.
import { useState } from "react";
import styled from "styled-components";
import logo from "./assets/logo.svg";
const StyledHeader = styled.header`
---
button {
---
span {
---
&:nth-child(even) {
margin: 5px 0;
}
}
}
.mobile-menu {
position: absolute;
right: 100px;
top: 100px;
display: ${(props) => (props.active ? "none" : "block")};
height: 330px;
width: 330px;
background: #e210e2;
color: white;
ul {
----
}
}
`;
const Header = () => {
const [active, setActive] = useState(false);
return (
<StyledHeader>
<img src={logo} alt="sunnyside logo" />
<button onClick={() => setActive(!active)}>
{console.log(active)}
<span></span>
<span></span>
<span></span>
</button>
<nav className="mobile-menu" active>
<ul>
<li>About</li>
<li>Services</li>
<li>Projects</li>
<li>Contact</li>
</ul>
</nav>
</StyledHeader>
);
};
export default Header;
Please pass the props in the StyledHeader tag.
Follow the below code:
<StyledHeader active={active}>
....
</StyledHeader>
You're not passing the active prop. You need to pass the active prop to the StyledHeader component to apply the styles like below.
<StyledHeader active={active}>
Updated Code will be like this.
<StyledHeader active={active}>
<img src={logo} alt="sunnyside logo" />
<button onClick={() => setActive(!active)}>
{console.log(active)}
<span></span>
<span></span>
<span></span>
</button>
<nav className="mobile-menu" active>
<ul>
<li>About</li>
<li>Services</li>
<li>Projects</li>
<li>Contact</li>
</ul>
</nav>
</StyledHeader>

React Material UI textfield label problem

I have problem with material ui text field.
There is a form with more textinput. When I scroll down the page, the textinputs label overlap on the header. Could You any idea solve this problem.
Thank You for Your help!
Without scrolling
Scrolling
Code Sandbox: https://codesandbox.io/s/serverless-night-wpkrb?file=/src/App.js
Code from sandbox below:
textinput.js
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles((theme) => ({
root: {
"& > *": {
margin: theme.spacing(1),
width: "25ch"
}
}
}));
const id = (error) => {
if (error === true) {
return "outlined-error";
} else {
return "outlined";
}
};
const shrink = (arg) => {
// ez a func biztosítja, hogy teljes label legyen és ne legyen kezelési hiba
if (arg === "") {
return false;
} else {
return true;
}
};
export default function BasicTextFields(props) {
const classes = useStyles();
return (
<form className={classes.root} noValidate autoComplete="off">
<TextField
error={props.error}
id={id(props.error)}
label={props.label}
variant="outlined"
onChange={props.change}
style={{ width: props.width }}
value={props.value}
InputLabelProps={{ shrink: shrink(props.value) }}
type={props.type}
inputProps={{ maxLength: props.maxlength }}
/>
</form>
);
}
App.js
import React from "react";
import "./styles.css";
import "w3-css/w3.css";
import BasicTextFields from "./textinput";
export default function App() {
return (
<div className="body">
<div className="w3-top w3-padding-8 w3-border-bottom w3-border-black">
<div className="w3-center w3-padding-16">
<div className="t1">
TündErella - <span style={{ fontSize: 45 }}> some text here.</span>{" "}
</div>
</div>
</div>
<div style={{ marginTop: 200 }}>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
<div className="name">
<BasicTextFields label="Vezetéknév: *"></BasicTextFields>
<BasicTextFields label="Keresztnév: *"></BasicTextFields>
</div>
<div className="name">
<BasicTextFields label="Vezetéknév: *"></BasicTextFields>
<BasicTextFields label="Keresztnév: *"></BasicTextFields>
</div>
<div className="name">
<BasicTextFields label="Vezetéknév: *"></BasicTextFields>
<BasicTextFields label="Keresztnév: *"></BasicTextFields>
</div>
<div className="name">
<BasicTextFields label="Vezetéknév: *"></BasicTextFields>
<BasicTextFields label="Keresztnév: *"></BasicTextFields>
</div>
</div>
);
}
styles.css
.App {
font-family: sans-serif;
text-align: center;
}
.body {
border: 1px solid white;
/*background-image: url("./static/background_maarten-deckers_1.jpg");*/
background-color: ivory;
}
.w3-top {
background-color: #daf0da;
}
.t1 {
font-size: 60px;
font-family: "Great Vibes", cursive;
}
The label for outlined TextField is rendered with a z-index of 1. This is the same z-index as applied by w3-top.
You need to bump up the z-index of w3-top in your styles.css:
.w3-top {
background-color: #daf0da;
z-index: 2;
}
In order for these styles to win over the styles defined in w3-css, you need to flip the order of your imports
from:
import "./styles.css";
import "w3-css/w3.css";
to:
import "w3-css/w3.css";
import "./styles.css";
Here's a working example: https://codesandbox.io/s/override-w3-top-z-index-k5fjv?file=/src/styles.css:198-252

Full screen drag and drop files in React

In this official example of react-dropzone, a full screen drop zone is achieved by wrapping the whole app inside the <Dropzone /> component. I am creating a multi route app and feel that wrapping everything inside the <Dropzone /> component is not a very clean solution.
Is there a way to create a full screen/page drop zone in React without placing the <Dropzone /> component on the root level?
Create a route to a Dropzone form and adjust the height and size of the field by utilizing CSS.
Working example: https://codesandbox.io/s/l77212orwz (this example uses Redux Form, but you don't have to)
container/UploadForm.js
import React, { Component } from "react";
import { reduxForm } from "redux-form";
import ShowForm from "../components/showForm";
class UploadImageForm extends Component {
state = { imageFile: [] };
handleFormSubmit = formProps => {
const fd = new FormData();
fd.append("imageFile", formProps.imageToUpload[0]);
// append any additional Redux form fields
// create an AJAX request here with the created formData
};
handleOnDrop = newImageFile => this.setState({ imageFile: newImageFile });
resetForm = () => {
this.setState({ imageFile: [] });
this.props.reset();
};
render = () => (
<div style={{ padding: 10 }}>
<ShowForm
handleOnDrop={this.handleOnDrop}
resetForm={this.resetForm}
handleFormSubmit={this.handleFormSubmit}
{...this.props}
{...this.state}
/>
</div>
);
}
export default reduxForm({ form: "UploadImageForm" })(UploadImageForm);
components/showForm.js
import isEmpty from "lodash/isEmpty";
import React from "react";
import { Form, Field } from "redux-form";
import DropZoneField from "./dropzoneField";
const imageIsRequired = value => (isEmpty(value) ? "Required" : undefined);
export default ({
handleFormSubmit,
handleOnDrop,
handleSubmit,
imageFile,
pristine,
resetForm,
submitting
}) => (
<Form onSubmit={handleSubmit(handleFormSubmit)}>
<Field
name="imageToUpload"
component={DropZoneField}
type="file"
imagefile={imageFile}
handleOnDrop={handleOnDrop}
validate={[imageIsRequired]}
/>
<button
type="submit"
className="uk-button uk-button-primary uk-button-large"
disabled={submitting}
>
Submit
</button>
<button
type="button"
className="uk-button uk-button-default uk-button-large"
disabled={pristine || submitting}
onClick={resetForm}
style={{ float: "right" }}
>
Clear
</button>
</Form>
);
components/dropzoneField.js
import React, { Fragment } from "react";
import DropZone from "react-dropzone";
import { MdCloudUpload } from "react-icons/md";
import RenderImagePreview from "./renderImagePreview";
export default ({
handleOnDrop,
input,
imagefile,
meta: { error, touched }
}) => (
<div>
<DropZone
accept="image/jpeg, image/png, image/gif, image/bmp"
className="upload-container"
onDrop={handleOnDrop}
onChange={file => input.onChange(file)}
>
<div className="dropzone-container">
<div className="dropzone-area">
{imagefile && imagefile.length > 0 ? (
<RenderImagePreview imagefile={imagefile} />
) : (
<Fragment>
<MdCloudUpload style={{ fontSize: 100, marginBottom: 0 }} />
<p>Click or drag image file to this area to upload.</p>
</Fragment>
)}
</div>
</div>
</DropZone>
{touched && error && <div style={{ color: "red" }}>{error}</div>}
</div>
);
components/renderImagePreview.js
import map from "lodash/map";
import React from "react";
export default ({ imagefile }) =>
map(imagefile, ({ name, preview, size }) => (
<ul key={name}>
<li>
<img src={preview} alt={name} />
</li>
<li style={{ textAlign: "center" }} key="imageDetails">
{name} - {size} bytes
</li>
</ul>
));
styles.css
.dropzone-container {
text-align: center;
background-color: #efebeb;
height: 100%;
width: 100%;
}
.dropzone-area {
margin: 0;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.upload-container {
height: 100vh;
width: 100%;
margin-bottom: 10px;
}
ul {
list-style-type: none;
}
p {
margin-top: 0;
}

Resources