How can I convert a function into a class in React? - reactjs

I'm trying to create this sliding sign in /sign up portal but the original code was on Vanilla JS. The components seems unmounted on the Dom and the program is unable to find the Classlist by its id.I did few attempts on using Component did mount but it is throwing error, later I've found out that I am lacking understanding about Class vs function on react. componentDidMount() seems to be only for Classes. Now I cant seem to find a valid solution for this. Also I might forget, when should I really need to use Classes vs functions in rendering a component? How can I prevent calling an unmounted element in the DOM if I use function instead of class?
This is the raw Html,css,vanilla js code for the portal.
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
signUpButton.addEventListener('click', () => {
container.classList.add("right-panel-active");
});
signInButton.addEventListener('click', () => {
container.classList.remove("right-panel-active");
});
#import url('https://fonts.googleapis.com/css?family=Montserrat:400,800');
* {
box-sizing: border-box;
}
body {
background: #f6f5f7;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: 'Montserrat', sans-serif;
height: 100vh;
margin: -20px 0 50px;
}
h1 {
font-weight: bold;
margin: 0;
}
h2 {
text-align: center;
}
p {
font-size: 14px;
font-weight: 100;
line-height: 20px;
letter-spacing: 0.5px;
margin: 20px 0 30px;
}
span {
font-size: 12px;
}
a {
color: #333;
font-size: 14px;
text-decoration: none;
margin: 15px 0;
}
button {
border-radius: 20px;
border: 1px solid #FF4B2B;
background-color: #FF4B2B;
color: #FFFFFF;
font-size: 12px;
font-weight: bold;
padding: 12px 45px;
letter-spacing: 1px;
text-transform: uppercase;
transition: transform 80ms ease-in;
}
button:active {
transform: scale(0.95);
}
button:focus {
outline: none;
}
button.ghost {
background-color: transparent;
border-color: #FFFFFF;
}
form {
background-color: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 50px;
height: 100%;
text-align: center;
}
input {
background-color: #eee;
border: none;
padding: 12px 15px;
margin: 8px 0;
width: 100%;
}
.container {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 14px 28px rgba(0,0,0,0.25),
0 10px 10px rgba(0,0,0,0.22);
position: relative;
overflow: hidden;
width: 768px;
max-width: 100%;
min-height: 480px;
}
.form-container {
position: absolute;
top: 0;
height: 100%;
transition: all 0.6s ease-in-out;
}
.sign-in-container {
left: 0;
width: 50%;
z-index: 2;
}
.container.right-panel-active .sign-in-container {
transform: translateX(100%);
}
.sign-up-container {
left: 0;
width: 50%;
opacity: 0;
z-index: 1;
}
.container.right-panel-active .sign-up-container {
transform: translateX(100%);
opacity: 1;
z-index: 5;
animation: show 0.6s;
}
#keyframes show {
0%, 49.99% {
opacity: 0;
z-index: 1;
}
50%, 100% {
opacity: 1;
z-index: 5;
}
}
.overlay-container {
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
overflow: hidden;
transition: transform 0.6s ease-in-out;
z-index: 100;
}
.container.right-panel-active .overlay-container{
transform: translateX(-100%);
}
.overlay {
background: #FF416C;
background: -webkit-linear-gradient(to right, #FF4B2B, #FF416C);
background: linear-gradient(to right, #FF4B2B, #FF416C);
background-repeat: no-repeat;
background-size: cover;
background-position: 0 0;
color: #FFFFFF;
position: relative;
left: -100%;
height: 100%;
width: 200%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.container.right-panel-active .overlay {
transform: translateX(50%);
}
.overlay-panel {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 0 40px;
text-align: center;
top: 0;
height: 100%;
width: 50%;
transform: translateX(0);
transition: transform 0.6s ease-in-out;
}
.overlay-left {
transform: translateX(-20%);
}
.container.right-panel-active .overlay-left {
transform: translateX(0);
}
.overlay-right {
right: 0;
transform: translateX(0);
}
.container.right-panel-active .overlay-right {
transform: translateX(20%);
}
.social-container {
margin: 20px 0;
}
.social-container a {
border: 1px solid #DDDDDD;
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
margin: 0 5px;
height: 40px;
width: 40px;
}
footer {
background-color: #222;
color: #fff;
font-size: 14px;
bottom: 0;
position: fixed;
left: 0;
right: 0;
text-align: center;
z-index: 999;
}
footer p {
margin: 10px 0;
}
footer i {
color: red;
}
footer a {
color: #3c97bf;
text-decoration: none;
}
<div class="container" id="container">
<div class="form-container sign-up-container">
<form action="#">
<h1>Create Account</h1>
<div class="social-container">
<i class="fab fa-facebook-f"></i>
<i class="fab fa-google-plus-g"></i>
<i class="fab fa-linkedin-in"></i>
</div>
<span>or use your email for registration</span>
<input type="text" placeholder="Name" />
<input type="email" placeholder="Email" />
<input type="password" placeholder="Password" />
<button>Sign Up</button>
</form>
</div>
<div class="form-container sign-in-container">
<form action="#">
<h1>Sign in</h1>
<div class="social-container">
<i class="fab fa-facebook-f"></i>
<i class="fab fa-google-plus-g"></i>
<i class="fab fa-linkedin-in"></i>
</div>
<span>or use your account</span>
<input type="email" placeholder="Email" />
<input type="password" placeholder="Password" />
Forgot your password?
<button>Sign In</button>
</form>
</div>
<div class="overlay-container">
<div class="overlay">
<div class="overlay-panel overlay-left">
<h1>Welcome Back!</h1>
<p>To keep connected with us please login with your personal info</p>
<button class="ghost" id="signIn">Sign In</button>
</div>
<div class="overlay-panel overlay-right">
<h1>Hello, Friend!</h1>
<p>Enter your personal details and start journey with us</p>
<button class="ghost" id="signUp">Sign Up</button>
</div>
</div>
</div>
</div>
And this is my current Login.js for my portal on a function.
import React, { useState } from 'react';
import axios from 'axios';
import { setUserSession } from './Utils/Common';
import './Login.css';
function Login(props) {
const [loading, setLoading] = useState(false);
const username = useFormInput('');
const password = useFormInput('');
const [error, setError] = useState(null);
const handleLogin = () => {
setError(null);
setLoading(true);
axios.post('http://localhost:4000/users/signin', { username: username.value, password: password.value }).then(response => {
console.log(username, password);
setLoading(false);
setUserSession(response.data.token, response.data.user);
props.history.push('/dashboard');
}).catch(error => {
setLoading(false);
if (error.response.status === 401) setError(error.response.data.message);
else setError("Something went wrong. Please try again later.");
});
}
const Signup = () => {
setError(null);
setLoading(true);
props.history.push('/Signup');
}
return (
<div className='login-wrapper' >
<div className='user-wrapper'>
<h1>Library Management System</h1>
<br />
<h1>Login</h1>
<br /><br />
<div className="user-details">
<h3>Username</h3>
<img src={userlogo} className="login-logo-user" />
<input type="text" {...username} autoComplete="new-password" />
</div>
<div className="user-details">
<h3>Password</h3>
<img src={passwordlogo} className="login-logo-password"/>
<input type="password" {...password} autoComplete="new-password" />
</div>
{error && <><small style={{ color: 'red' }}>{error}</small><br /></>}<br />
<input type="button" value={loading ? 'Loading...' : 'Login'} onClick={handleLogin} disabled={loading} id='buttons'/>
<input type="button" value={loading ? 'Loading...' : 'Signup'} onClick={Signup} id='buttons'/>
<div className="forgot-password">
<h5>Forgot Password? Click <span id="forgot-password">here</span>.</h5>
</div>
</div>
<div className='logo-wrapper'>
<div className="logo-main">
<img src={librarylogo} id="mainlogo"/>
<h2>Library Management System v1.0</h2>
</div>
</div>
</div>
);
}
const useFormInput = initialValue => {
const [value, setValue] = useState(initialValue);
const handleChange = e => {
setValue(e.target.value);
}
return {
value,
onChange: handleChange
}
}
export default Login;
Is this correct by the way?
I am trying to convert this as well?
from this function.
function login(props) {
const [loading, setLoading] = useState(false);
const username = useFormInput('');
const password = useFormInput('');
const [error, setError] = useState(null);
}
into a class:
class Login extends React.Component{
constructor(props) {
super(props);
this.state = {
loading, setLoading : false,
username : useFormInput(''),
password : useFormInput(''),
error, setError = null
}
}
}

I got it working now. Thanks for all the help.
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: false,
setLoading: false,
email: props.email,
password: props.password,
error: null,
setError: null
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount(){
const signUpButton = document.getElementById('signUp');
const signInButton = document.getElementById('signIn');
const container = document.getElementById('container');
if (container){
console.log('loaded');
signUpButton.addEventListener('click', () => {
container.classList.add("right-panel-active");
});
signInButton.addEventListener('click', () => {
container.classList.remove("right-panel-active");
});
}
}
handleChange(event) {
this.setState({
[event.target.type]: event.target.value
});
}
handleSubmitSignIn(event) {
// alert('A name was submitted: ' + this.state.email + this.state.password);
event.preventDefault();
console.log(this.state.email);
console.log(this.state.password);
}
handleSubmitSignUp(event) {
// alert('A name was submitted: ' + this.state.email + this.state.password);
event.preventDefault();
console.log(this.state.email);
console.log(this.state.password);
}
render() {
return (
<div className="container" id="container">
<div className="form-container sign-up-container">
<form onSubmit={this.handleSubmitSignUp}>
<h1>Create Account</h1>
<div className="social-container">
<i className="fab fa-facebook-f"></i>
<i className="fab fa-google-plus-g"></i>
<i className="fab fa-linkedin-in"></i>
</div>
<span>or use your email for registration</span>
<input type="text" placeholder="Name" autoComplete="new-name" />
<input type="email" placeholder="Email" autoComplete="new-email" />
<input type="password" placeholder="Password" autoComplete="new-password" />
<input type="department" placeholder="Department" autoComplete="new-name" />
<input type="year" placeholder="Year" autoComplete="new-email" />
<input type="schoolId" placeholder="School Id No." autoComplete="new-password" />
<button>Sign Up</button>
</form>
</div>
<div className="form-container sign-in-container">
<form onSubmit={this.handleSubmitSignIn}>
<h1>Sign in</h1>
<div className="social-container">
<i className="fab fa-facebook-f"></i>
<i className="fab fa-google-plus-g"></i>
<i className="fab fa-linkedin-in"></i>
</div>
<span>or use your account</span>
<input type="email" placeholder="Email" value={this.state.email} autoComplete='new-email' onChange={this.handleChange}/>
<input type="password" placeholder="Password" value={this.state.password} autoComplete='new-password' onChange={this.handleChange}/>
Forgot your password?
<button type='submit' >Sign In</button>
</form>
</div>
<div className="overlay-container">
<div className="overlay">
<div className="overlay-panel overlay-left">
<h1>Welcome Back!</h1>
<p>To keep connected with us please login with your personal info</p>
<button className="ghost" id="signIn">Sign In</button>
</div>
<div className="overlay-panel overlay-right">
<h1>Hello</h1>
<p>Enter your personal details and start journey with us</p>
<button className="ghost" id="signUp">Sign Up</button>
</div>
</div>
</div>
</div>
);
}
}
export default Login;

Related

After removing the text area, not able to add again or add other options in a react app

On click on the Text Area, button should add relevant text area in a pag. By clicking on the close button, system should remove the added textarea in a React page. By default, the close button shouldn't display. In this example, system is adding the text area, but once it is removed, I am not able to add the textarea anymore. Could someone please advise the issue here.
CSB link:
https://codesandbox.io/s/nervous-currying-jojdhi?file=/src/App.js
import "./styles.css";
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
export default function App() {
const [multiInput, setMultiInput] = useState("");
const [createCode, setCreateCode] = useState("");
const [createImageTag, setImageTag] = useState("");
const [visible, setVisible] = useState(true);
const createCodeSection = () => {
const newElement = React.createElement("blockquote", {
contenteditable: "true",
className: "codehighlight",
name: "codesection" + new Date().getTime()
});
setCreateCode((createCode) => [...createCode, newElement]);
};
const createMultilineTextSection = () => {
const newElement = React.createElement("textarea", {
contenteditable: "true",
className: "defaultTextArea",
name: "textarea" + new Date().getTime()
});
setCreateCode((multiInput) => [...multiInput, newElement]);
};
const createImageSection = () => {
const newElement = React.createElement("img", {
key: "ele" + new Date().getTime()
});
setCreateCode((createImageTag) => [...createImageTag, newElement]);
};
const removeElement = () => {
setVisible((prev) => !prev);
};
return (
<div id="App">
<div className="adminSection">
<div className="row">
<div className="logout"></div>
<div className="createBlogSection">
<div className="row">
<button onClick={createMultilineTextSection}>Text Area</button>
<button onClick={createCodeSection}>Code</button>
<button>Image</button>
</div>{" "}
<br></br>
<div className="row">
<textarea className="defaultTextArea"></textarea>
</div>
<br></br>
<div className="row">
{visible && <span className="dtextArea">{createCode}</span>}
</div>
<div className="row">
{visible && (
<div>
<span className="closeElement">
<button onClick={removeElement}>X</button>
</span>
<span>{multiInput}</span>
</div>
)}
</div>
</div>
</div>
</div>
</div>
);
}
//css
.App {
font-family: sans-serif;
text-align: center;
}
.adminSection {
width: 100%;
}
.adminSection h1 {
margin: 25px 0px 0px 550px !important;
color: black !important;
}
.logout img {
height: 30px;
width: 30px;
margin: -100px 50px 0px 0px;
float: right;
}
.createBlogSection {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(700px, 1fr));
grid-gap: 25px !important;
margin: 100px 20px 10px 20px !important;
/* border: solid 1px; */
border-color: #e2e8f0;
border-radius: 0px 5px 5px 0px !important;
background-color: #fff;
}
.defaultTextArea {
height: 100px;
width: 300px;
margin: 10px 0px 10px 40px;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
background-color: #fff !important;
}
.codehighlight {
width: 100%;
color: #fff;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
background-color: #353232 !important;
}
.closeElement {
margin-left: 320px;
display: none;
}
Instead of how you've put the added elements, use:
const removeElement = (index) => {
const newElements = multiInput.filter((_, i) => i == index);
setMultiInput(newElements);
};
// Inside "return" (createBlogSection div)
multiInput.map((_input, index) => {
<div key={index}>
{_input}
<span className="closeElement">
<button onClick={removeElement(index)}>X</button>
</span>
</div>
})
Edit:
Add const [multiInput, setMultiInput] = useState([]); and instead of pushing new elements into separate variables add all into multiInput only. Using setMultiInput(multiInput) => [...multiInput, newElement]); in each case.

How do I Setup a excel like filter using react-data-table-component

Been searching on how to make a excel like filter using react-data-table-component, and found something interesting, like Data Table filtering using react-data-table-component.
Unfortunately, the FilterComponent Component seems to be deprecated, since I can't find anything regarding it but broken links, which is weird for such a interesting feature.
My code is the following:
const columns = Properties.columns;
const getSubHeaderComponent = () => {
return (
<FilterComponent
onFilter={(e) => {
let newFilterText = e.target.value;
filteredItems = statements.filter(
(item) =>
item.name &&
item.name.toLowerCase().includes(newFilterText.toLowerCase())
);
this.setState({ filterText: newFilterText });
}}
onClear={handleClear}
filterText={filterText}
/>
);
};
return (
<div>
<div className="row justify-content-md-center statements-table">
<div className="col-md-10">
<DataTable
columns={columns}
data={statements}
customStyles={Properties.customStyles}
fixedHeader
fixedHeaderScrollHeight="47em"
pagination
subheader
subHeaderComponent={getSubHeaderComponent()}
paginationPerPage={100}
paginationRowsPerPageOptions={[100, 500, 1000]}
subHeader
noHeader
/>
</div>
</div>
Any suggestions?
FilterComponent could be something as simple as
const FilterComponent = ({ filterText, onFilter, onClear }) => (
<div>
<input
type="text"
value={filterText}
onChange={onFilter}
/>
<button type="button" onClick={onClear}>
X
</button>
</div>
);
However, I found following official implementation of FilterComponent on Examples/Filtering | React Data Table Components (also referred Button.js) if you need it like that.
const TextField = styled.input`
height: 32px;
width: 200px;
border-radius: 3px;
border-top-left-radius: 5px;
border-bottom-left-radius: 5px;
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border: 1px solid #e5e5e5;
padding: 0 32px 0 16px;
&:hover {
cursor: pointer;
}
`;
const ButtonStyle = styled.button`
background-color: #2979ff;
border: none;
color: white;
padding: 8px 32px 8px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
border-radius: 3px;
&:hover {
cursor: pointer;
}
`;
const Button = ({ children, ...rest }) => <ButtonStyle {...rest}>{children}</ButtonStyle>;
const ClearButton = styled(Button)`
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
height: 34px;
width: 32px;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
`;
const FilterComponent = ({ filterText, onFilter, onClear }) => (
<>
<TextField
id="search"
type="text"
placeholder="Filter By Name"
aria-label="Search Input"
value={filterText}
onChange={onFilter}
/>
<ClearButton type="button" onClick={onClear}>
X
</ClearButton>
</>
);

Adding New Input Field using button in ReactJs

I am working on a project so I am trying to add a new input field after clicking the add(+) button in the form using react-Hooks. It would be very helpful if someone can figure this out so I can learn a new thing. Thankyou in advance.[React events handling link is added][1]
Here is the code of the form and css file
import Navbar from "./Navbar/Navbar";
import "./UserDetails.css";
function UserDetails() {
const [Info, setInfo] = useState({
username: "",
email: "",
bio: "",
positions: "",
});
const { username, email, bio, positions } = Info;
const onChange = (e) => setInfo({ ...Info, [e.target.name]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
console.log(Info);
};
return (
<div>
<Navbar />
<div className="full">
<h1 className="top">Edit Profile</h1>
<img
className="pic"
src="https://www.pngitem.com/pimgs/m/146-1468479_my-profile-icon-blank-profile-picture-circle-hd.png"
alt=""
></img>
<div className="inputs">
<form className="frms" onSubmit={(e) => onSubmit(e)}>
<input
className="insides"
type="text"
placeholder="Username"
name="username"
value={username}
onChange={(e) => onChange(e)}
></input>
<input
className="insides"
type="email"
placeholder="email"
name="email"
value={email}
onChange={(e) => onChange(e)}
></input>
<textarea
placeholder="Add Bio here..."
name="bio"
value={bio}
onChange={(e) => onChange(e)}
></textarea>
</form>
</div>
<div className="addbtn">
<input
className="insidesp"
type="text"
placeholder="positions held..."
name="positions"
value={positions}
onChange={(e) => onChange(e)}
></input>
<button>+</button>
<br></br>
<button className="savebtn">Save Changes</button>
</div>
</div>
</div>
);
}
export default UserDetails;
.full {
text-align: center;
border: 2px solid white;
margin: 0 auto;
padding-top: 1%;
width: 50%;
padding-bottom: 1%;
margin-top: 2%;
border-radius: 30px;
box-shadow: 5px 6px 5px 6px rgb(158, 170, 238);
}
.top {
color: rgb(88 99 161);
}
.pic {
height: 40%;
width: 30%;
}
.inputs input {
display: block;
width: 70%;
margin: 0 auto;
margin-top: 2%;
border: 2px solid rgb(88 99 161);
border-radius: 7px;
}
.inputs textarea {
display: block;
width: 70%;
margin: 0 auto;
margin-top: 2%;
border: 2px solid rgb(88 99 161);
border-radius: 7px;
}
.pic {
margin: 2%;
}
.savebtn {
margin-top: 2%;
background-color: rgb(88 99 161);
border: 2px solid rgb(158, 170, 238);
border-radius: 6px;
}
.addbtn {
display: inline;
}
.addbtn input {
margin-right: 1%;
width: 65%;
margin-top: 2%;
border: 2px solid rgb(88 99 161);
border-radius: 7px;
}
.addbtn button {
background-color: rgb(88 99 161);
border-radius: 6px;
border: 2px solid rgb(158, 170, 238);
}```
[1]: https://reactjs.org/docs/handling-events.html
Here is a great article that explains solution for your question step by step:
https://www.cluemediator.com/add-or-remove-input-fields-dynamically-with-reactjs

Input checkbox didn't work what I expected

I tried to make an input checkbox when I click the input checkbox, it should be displayed a check image like this.
However, it didn't show the checkbox and I am not sure how to check that the input box was checked or not. Could you help me with what part do I missed and where is something wrong?
I really appreciate your help!
This is CSS inputl and label part
.colors {
display: flex;
flex-direction: column;
span {
margin-bottom: 20px;
}
.colorLists {
margin-left: 10px;
display: flex;
flex-wrap: wrap;
.colorLayout {
display: flex;
flex-direction: column;
position: relative;
width: 33%;
height: 80px;
flex-shrink: 0;
align-items: center;
justify-content: center;
.checkboxLabel {
background-color: beige;
border: 1px solid #ccc;
border-radius: 50%;
cursor: pointer;
height: 28px;
left: 0;
position: absolute;
top: 40;
width: 28px;
&:after {
border: 2px solid #fff;
border-top: none;
border-right: none;
content: '';
height: 6px;
left: 7px;
opacity: 0;
position: absolute;
top: 8px;
transform: rotate(-45deg);
width: 12px;
// opacity: 0.2;
}
}
input[type='checkbox'] {
visibility: hidden;
}
input[type='checkbox']:checked {
& + label {
background-color: beige;
border-color: beige;
&:after {
opacity: 1;
}
}
}
.productColor {
margin-top: 70px;
font-size: 13px;
margin-right: 21px;
}
}
}
}
.sizes {
.HorizontalLine {
margin-top: 25px;
}
.span {
}
.sizeLists {
margin-top: 20px;
margin-bottom: 20px;
button {
margin: 5px;
width: 44px;
height: 32px;
background-color: white;
border: 1px solid silver;
border-radius: 15%;
}
}
}
This is js part
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input type="checkbox" />
<label
className="checkboxLabel"
for="checkbox"
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
In react you have to set the htmlFor property for the label instead of for.
The value should be the same as the id from the input.
Then you can add a value property for the input which is used for adding/removing the item in the list of selected items.
For this purpose a handleChange function can be defined.
const [selectedItems, setSelectedItems] = useState([]);
function handleChange(e) {
let newSelected = [];
if (selectedItems.includes(e.target.value)) {
newSelected = selectedItems.filter((item) => item !== e.target.value);
} else {
newSelected = [...selectedItems, e.target.value];
}
setSelectedItems(newSelected);
}
return (
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input
onChange={handleChange}
type="checkbox"
id={idx}
value={color.color_name}
checked={selectedItems.includes(color.color_name)}
/>
<label
className="checkboxLabel"
htmlFor={idx}
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
);
EDIT: Since you are using a class component it can be rewrittenlike this:
export default class CheckboxListComponent extends Component {
constructor(props) {
super(props);
this.state = { selectedItems: [] };
this.handleChange = this.handleChange.bind(this);
}
handleChange(e) {
let newSelected = [];
if (this.state.selectedItems.includes(e.target.value)) {
newSelected = this.state.selectedItems.filter(
(item) => item !== e.target.value
);
} else {
newSelected = [...this.state.selectedItems, e.target.value];
}
this.setState({ selectedItems: newSelected });
}
render() {
return (
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" key={idx}>
<input
onChange={this.handleChange}
type="checkbox"
id={idx}
value={color.color_name}
checked={this.state.selectedItems.includes(color.color_name)}
/>
<label
className="checkboxLabel"
htmlFor={idx}
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
);
}
}
You must tell react that your input is checked so that your CSS will apply it. selected ids must be kept in a place for future existence check. in the following code, I named this array selecetedIdx.
You also need to add idx on selection(via onChange event handler) or wrap them all in form and add them via extra dom attribute.
class Main extends Component {
// initialize selectedIdx with [] in your state (esp constructor)
// e.g. this.state = {/* rest of state, */ selectedIdx: []}
render() {
return (
{COLOR_LISTS.map((color, idx) => {
return (
// ...
<input
type="checkbox"
checked={selectedIdx.includes(idx)}
onChange={() => this.setState(state => ({
selectedIdx: [...state.selectedIdx, idx]
}))}
/>
// ...
)}
)
}
Your checkbox element needs name and value properties and would normally be a child of the <form> element.

How to get a particular div into fullscreen(full window size) in reactjs

I am making a Image viewer in ReactJs as I am newbie in this so I stuck at a point. actually I have to add a full screen option. when user click on any particular image the image is open and there is a option like next,prev,close,rotate and fullscreen(that is takes height and width of browser) so when user click on full screen that particular image will get the full window size and user still have option like rotate,next.close and prev. I searched for so many solution but nothing worked.
I tried so many things but it only does the fullscreen whole body but I want .center-image to be full screen with options as I said. This is the gallary modal component.
class GalleryModal extends React.Component {
constructor(props) {
super(props);
this.state = {
rotation: 0
};
this.rotate = this.rotate.bind(this);
}
render() {
const { rotation } = this.state;
if (this.props.isOpen === false) {
return null;
}
return (
<div className="modal-overlay" name={this.props.name}>
<div className="modal-body">
<a href="#" className="button" onClick={() => this.rotate()}>
<i className="fas fa-sync-alt" />
</a>
<a href="#" className="button" onClick={this.props.onPrev}>
<i className="fas fa-angle-left" />
</a>
<img
className="center_image"
id="image"
src={this.props.src}
style={{ transform: `rotate(${rotation}deg)` }}
/>
<a href="#" className="button" onClick={this.props.onNext}>
<i className="fas fa-angle-right" />
</a>
<a
className="modal-close"
href="#"
onClick={this.props.onClick}
>
<span className="fa fa-times" />
</a>
</div>
</div>
);
}
rotate() {
let newRotation = this.state.rotation + 90;
if (newRotation >= 360) {
newRotation = -360;
}
this.setState({
rotation: newRotation
});
}
}
Full code
This is my code and I am confused how to add the fullscreen option and where to add it .
I recommend using css viewport units, setting a component to height: 100vh and width: 100vw will make it fullscreen. You then conditionally render the component based on when you want it to be fullscreen.
Had to use some css tricks, but I believe this is what you're looking to achieve. The image is centered and takes up the maximum amount of width that is available within the window; however, if you stretch the window, it'll adjust its width up until it hits its max width (not advised to stretch it beyond its max value, otherwise, you'll get pixelation).
I did simplify your code a bit by elevating state and class methods to a single container, as well as, used setState() callbacks to manage state more efficiently and the ternary operator (cond ? true : false) in replace of simple if/else conditional statements.
Working example: https://codesandbox.io/s/zr5k7v0zp3
containers/Gallery/Gallery.js
import React from "react";
import GalleryImages from "../../components/GalleryImages/galleryImages";
import GalleryModal from "../../components/GalleryModal/galleryModal";
const imgUrls = [
"https://source.unsplash.com/3Z70SDuYs5g/800x600",
"https://source.unsplash.com/01vFmYAOqQ0/800x600",
"https://source.unsplash.com/2Bjq3A7rGn4/800x600",
"https://source.unsplash.com/t20pc32VbrU/800x600",
"https://source.unsplash.com/pHANr-CpbYM/800x600",
"https://source.unsplash.com/3PmwYw2uErY/800x600",
"https://source.unsplash.com/uOi3lg8fGl4/800x600",
"https://source.unsplash.com/CwkiN6_qpDI/800x600",
"https://source.unsplash.com/9O1oQ9SzQZQ/800x600",
"https://source.unsplash.com/E4944K_4SvI/800x600",
"https://source.unsplash.com/-hI5dX2ObAs/800x600",
"https://source.unsplash.com/vZlTg_McCDo/800x600"
];
export default class Gallery extends React.Component {
constructor(props) {
super(props);
this.state = {
imgIndex: 0,
imgUrlLength: imgUrls.length,
showModal: false,
rotation: 0
};
this.openModal = this.openModal.bind(this);
this.closeModal = this.closeModal.bind(this);
this.nextClick = this.nextClick.bind(this);
this.prevClick = this.prevClick.bind(this);
this.rotateImage = this.rotateImage.bind(this);
}
openModal(index) {
this.setState({
showModal: true,
imgIndex: index
});
}
closeModal() {
this.setState({
showModal: false,
imgIndex: 0,
rotation: 0
});
}
nextClick() {
this.setState(prevState => {
return {
imgIndex:
prevState.imgIndex === prevState.imgUrlLength - 1
? 0
: prevState.imgIndex + 1
};
});
}
prevClick() {
this.setState(prevState => {
return {
imgIndex:
prevState.imgIndex === 0
? prevState.imgUrlLength - 1
: prevState.imgIndex - 1
};
});
}
rotateImage() {
this.setState(prevState => {
return {
rotation: prevState.rotation + 90 <= 270 ? prevState.rotation + 90 : 0
};
});
}
render() {
return (
<div className="container-fluid gallery-container">
<GalleryImages imgUrls={imgUrls} openModal={this.openModal} />
<GalleryModal
isOpen={this.state.showModal}
onClick={this.closeModal}
onNext={this.nextClick}
onPrev={this.prevClick}
rotateImage={this.rotateImage}
rotation={this.state.rotation}
src={imgUrls[this.state.imgIndex]}
/>
</div>
);
}
}
components/GalleryImages/galleryImages.js
import React from "react";
import PropTypes from "prop-types";
const GalleryImages = ({ imgUrls, openModal }) => {
return (
<div className="row">
{imgUrls.map((url, index) => {
return (
<div key={index} className="col-sm-6 col-md-3 col-xl-2">
<div className="gallery-card">
<img
key={index}
className="gallery-thumbnail"
src={url}
alt={`Image number ${index + 1}`}
/>
<span
className="card-icon-open fa fa-expand"
onClick={() => openModal(index)}
/>
</div>
</div>
);
})}
</div>
);
};
GalleryImages.propTypes = {
imgUrls: PropTypes.arrayOf(PropTypes.string).isRequired,
openModal: PropTypes.func.isRequired
};
export default GalleryImages;
components/GalleryModal/galleryModal.js
import React from "react";
import PropTypes from "prop-types";
const GalleryModal = ({
isOpen,
onClick,
onNext,
onPrev,
rotateImage,
rotation,
src
}) => {
return isOpen ? (
<div className="modal-overlay">
<div className="modal-body">
<div className="close-modal">
<a className="modal-close" href="#" onClick={onClick}>
<span className="fa fa-times" />
</a>
</div>
<div className="rotate-container">
<a href="#" className="button" onClick={rotateImage}>
<i style={{ fontSize: 44 }} className="fas fa-sync-alt" />
</a>
</div>
<div className="image-container">
<div>
<a href="#" className="button" onClick={onPrev}>
<i className="fas fa-angle-left" />
</a>
</div>
<div>
<img
src={src}
style={{ transform: `rotate(${rotation}deg)`, width: "100%" }}
/>
</div>
<div>
<a href="#" className="button" onClick={onNext}>
<i className="fas fa-angle-right" />
</a>
</div>
</div>
</div>
</div>
) : null;
};
GalleryModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onClick: PropTypes.func.isRequired,
onNext: PropTypes.func.isRequired,
onPrev: PropTypes.func.isRequired,
rotateImage: PropTypes.func.isRequired,
rotation: PropTypes.number.isRequired,
src: PropTypes.string
};
export default GalleryModal;
styles.css
html,
body {
min-height: 100%;
height: 100%;
}
html {
font-size: 16px;
}
body {
position: relative;
font-size: 100%;
}
.button {
font-size: 50px;
color: #eee;
margin: 5px;
}
.card-icon-open {
display: block;
position: relative;
left: 45%;
top: 35px;
font-size: 30px;
width: 30px;
color: #fff;
cursor: pointer;
opacity: 0;
transform: translate(0%, -400%);
transition: all 0.25s ease-in-out;
}
.card-icon-open:focus,
.card-icon-open:hover {
color: #111;
}
.close-modal {
position: fixed;
top: 0;
right: 5px;
}
.fullscreen {
position: relative;
text-decoration: none;
font-size: 25px;
color: #eee;
z-index: 999;
}
.fullscreen:hover,
.fullscreen:focus,
.fullscreen:blur {
text-decoration: none;
color: red;
}
.gallery-container {
padding-top: 10px;
}
.gallery-card {
position: relative;
overflow: hidden;
margin-bottom: 10px;
}
.gallery-thumbnail {
max-width: 100%;
height: auto;
border-radius: 4px;
}
.gallery-thumbnail:focus ~ .card-icon-open,
.gallery-thumbnail:hover ~ .card-icon-open,
.gallery-thumbnail ~ .card-icon-open:focus,
.gallery-thumbnail ~ .card-icon-open:hover {
opacity: 1;
}
.image-container {
display: flex;
justify-content: center;
align-items: center;
}
.image-rotate {
font-size: 44px;
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
background: rgba(21, 21, 21, 0.75);
}
.modal-body {
position: relative;
top: 15%;
z-index: 11;
padding: 0;
overflow: hidden;
max-width: 100%;
max-height: 100%;
}
.modal-close {
font-size: 44px;
z-index: 99;
color: #eee;
transition: all 0.25s ease-in-out;
}
.modal-close:focus,
.modal-close:hover {
color: red;
}
.rotate-container {
font-size: 44px;
position: fixed;
top: 0;
left: 5px;
}
Found this library which does exactly what you describe:
https://www.npmjs.com/package/react-fullscreen-image
You can use as is or look into the code for guidance

Resources