I want to make components with two buttons aligned vertically in react - reactjs

I want to make a component with increment and decrement functionality. Increment and decrement arrow buttons are aligned vertically and a text on the right side of those buttons which is the counter and a reset button under it.
Here is the component that I want:

i made a simple code that is quite similar to what you want :
Here is the Code i wrote in App.js ( you can move the code later to in independant component ) :
import React from "react";
import "./App.css";
import { useState } from "react";
function App() {
const [counter, setCounter] = useState(0);
return (
<div class="grid-container">
<div class="grid-item" onClick={() => setCounter(counter + 1)}>
<i class="fas fa-2x fa-angle-up"></i>
</div>
<div class="grid-item">{counter}</div>
<div class="grid-item" onClick={() => setCounter(counter - 1)}>
<i class="fas fa-2x fa-angle-down"></i>
</div>
<div class="grid-item" onClick={() => setCounter(0)}>
Reset
</div>
</div>
);
}
export default App;
Now here is the App.css content ( for styling ) :
.grid-container {
display: grid;
grid-template-columns: auto auto;
background-color: #50404d;
height: 200px;
width: 200px;
}
.grid-item {
border: 1px solid #fff;
color: #fff;
padding: 30px 0;
font-size: 20px;
text-align: center;
}
Note: for the icons to work you need to add this piece of code in "public/index.html" inside the <header> tag :
<script
src="https://kit.fontawesome.com/a076d05399.js"
crossorigin="anonymous"
></script>
I hope this simple solution helps you get an idea .

Related

How can I do conditional rendering on a styled component?

I am using conditional rendering to make toggle function. But I think there is a problem with the method because I did conditional rendering on the styled component but it doesn't work. Can you tell me how to fix it? I'd appreciate it if you let me know thanks
my.jsx:
If I click on another image, the value of the profile becomes false, and if I click on the profile image, the value of the profile becomes true. And according to the value of the profile, I gave the value of the display by conditional rendering the tag whose className is IconWrap6True. But now, the display value of IconWrap6Trued keeps coming out as block, and 'none' is not applied. The cord is long, so I skipped the parts that I didn't need
import React, { useState } from 'react'
import styled from 'styled-components';
import defaultProfile from '../resources/images/img/defaultprofile.jpg'
const NavigationBarWrap1 = styled.div`
position: fixed;
flex-direction: column;
box-sizing: border-box;
display: flex;
flex-shrink: 0;
align-items: stretch;
.IconWrap6True {
${props => props.profile ? "block" : "none"};
box-sizing: border-box;
border-bottom-left-radius: 50%;
top: 50%;
border-top-right-radius: 50%;
left: 50%;
border: 2px solid rgb(38,38,38);
transform: translate(-50%,-50%);
}
`
function NavigationBar() {
//state
const[home, setHome] = useState(true);
const[profile,setProfile] = useState(true);
//true
const setTrueHome = () => {
setHome(true)
}
const setTrueProfile = () => {
setProfile(true)
}
//false
const setFalseHome = () => {
setHome(false)
}
const setFalseProfile = () => {
setProfile(false)
}
//handle
const forHome = (e) => {
setTrueHome();
setFalseProfile();
}
const forProfile = (e) => {
setFalseHome();
setTrueProfile();
}
return (
<NavigationBarWrap1>
<div className='IconWrap'>
<div className='IconWrap4'>
<div onClick={forHome} className='IconWrap5'>
<div>
<div className='IconWrap6'>
<div className='IconWrap7'>
{home===true?
<>
<img/>
</>:
<>
<img/>
</>}
</div>
</div>
</div>
</div>
</div>
</div>
<div className='IconWrap'>
<div className='IconWrap2'>
<div>
<div className='IconWrap6'>
<div profile={profile} className='IconWrap6True'/>
<div onclick={forProfile} className='IconWrap7'>
<img src={defaultProfile}/>
</div>
</div>
</div>
<div className='textWrap'>
<div className='textWrap2'>
<div className='textWrap3'>
프로필
</div>
</div>
</div>
</div>
</div>
</NavigationBarWrap1>
)
}
export default NavigationBar;
pass the profile prop to NavigationBarWrap1
<NavigationBarWrap1 profile={profile}>

How do I change the size of an element using useState?

I can maximize and minimize with the SIZE button. But if the user changes the size of the editor window manually, the code doesn't work. How can I fix it?
I think I have to change the useState to take a non-boolean value, but I don't know to what.
Here's the App.js code
import { useState } from 'react';
import Editor from './components/Editor';
function App() {
const [content, setContent] = useState("")
function handleChange(event) {
setContent(event.target.value)
}
const [editorSize, setEditorSize] = useState(true)
function toggleEditorSize() {
setEditorSize(prevState => !prevState)
}
return (
<div className="App">
<Editor handleChange={handleChange} toggleEditorSize={toggleEditorSize} editorSize={editorSize}/>
</div>
);
}
export default App;
Here's the Editor.js code
export default function Editor(props) {
return (
<div>
<div className="editor-header">
<p className="editor-title">Editor</p>
<button onClick={props.toggleEditorSize}>SIZE</button>
</div>
<textarea id="editor" className={props.editorSize ? "max": ""} onChange={props.handleChange} >
</textarea>
</div>
)
}
Here's the Index.css code
background-color: white;
color: black;
border: 2px solid black;
position: relative;
display: inline-block;
overflow: scroll;
border-top: none;
min-width: 500px;
min-height: 300px;
max-width: 500px;
max-height: 600px;
height: 300px;
}
#editor.max, #preview.max {
height: 600px;
}
Hear what's happening is you have render component to detect the changes happed. here everytime when you click button useEffect will run and check if editorSize is true or not. if it's then it will set "max" class name to state ( Size ) and then here
<textarea id="editor" className={Size} onChange={props.handleChange} >
</textarea>
className will be set. Well, this should work. if it doesn't works try adding important property to you css. like this,
#editor.max, #preview.max {
height: 600px !important;
}
Here's the Editor.js code
export default function Editor(props) {
const[Size, setSize] = useState("");
useEffect(()=>{
if(props.editorSize){
setSize("max")
} else {
setSize("")
}
},[props.editorSize]);
return (
<div>
<div className="editor-header">
<p className="editor-title">Editor</p>
<button onClick={props.toggleEditorSize}>SIZE</button>
</div>
<textarea id="editor" className={Size} onChange={props.handleChange} >
</textarea>
</div>
)
}

React paginate layout issue

I'm new with react and I'm trying to adapt my pagination to the design.
I'm not sure the react-paginate is the right one to use however I don't have much more expertise.
I managed to have something working but only with CSS, I don't like the hack approach.
is it possible to add Result found?
and page 1 of whatever?
my design should look like this:
But this is what I have at the moment:
And finally this is my react code:
<div className='paginate'>
<span className='result-found'>Result found</span>
<ReactPaginate
previousLabel="Back"
previousClassName="prev fa fa-caret-left"
nextLabel="Next"
nextClassName="next fa fa-caret-right"
breakLabel="..."
pageLinkClassName="page-link"
pageClassName="page"
breakClassName={""}
pageCount={total}
marginPagesDisplayed={1}
pageRangeDisplayed={4}
onPageChange={handlePageClick}
containerClassName="pagination"
subContainerClassName="pages pagination"
activeClassName="active"
/>
</div>
Here you go:
It is 90% CSS and 10% React. :D Edit the CSS for perfection. The code for the screenshot looks like this:
import { useEffect, useState } from "react";
import "./styles.css";
const PAGE_SIZE = 10;
export default function App() {
const [total, setTotal] = useState(42);
const [pageNo, setPageNo] = useState(0);
const maxPages = Math.ceil(total / PAGE_SIZE);
useEffect(() => {
// do your async call here
// set total
}, [pageNo]);
// take care of boundary condition like last and first pages
const onNext = () => pageNo < maxPages - 1 && setPageNo(pageNo + 1);
const onPrev = () => pageNo > 0 && setPageNo(pageNo - 1);
return (
<div className="App">
<div className="pagination-container">
<div className="pagination-left">
<span>{total} results found</span>
</div>
<div className="pagination-right">
<div className="pagination-current">
Page {pageNo + 1} of {maxPages}
</div>
<div className="pagination-buttons">
<div className="pagination-button-wrapper">
<button onClick={onPrev} className="pagination-button">
<
</button>
</div>
</div>
<div className="pagination-buttons">
<div className="pagination-button-wrapper">
<button onClick={onNext} className="pagination-button">
>
</button>
</div>
</div>
</div>
</div>
</div>
);
}
You can do usability enhancement by setting the buttons disabled={true} when the boundary condition reaches on first and last pages.
And the CSS is:
.pagination-container {
background-color: black;
display: flex;
justify-content: space-between;
padding: 1rem;
color: white;
}
.pagination-left {
display: flex;
align-items: center;
}
.pagination-right {
display: flex;
align-items: center;
}
.pagination-buttons {
display: flex;
margin-left: 0.5rem;
}
.pagination-buttons > * {
border: 1px solid white;
padding: 0.1rem 0.5rem;
}
.pagination-button {
background-color: transparent;
color: white;
border: 0;
}
Here also, you can edit CSS to match the exact style with arrows and buttons, and margins and paddings, and borders.
And a functional demo is here: https://codesandbox.io/s/zealous-ardinghelli-y4txu?file=/src/App.js
Larger Context: I assume you may want to reuse this component on multiple places. If so, you may want to extract out the logic into props. That means get rid of states and specialized logic (fetch data, in this case) to make it a stateless component by editing this component something like this:
interface Props {
onNext: () => void;
onPrev: () => void;
pageSize: number;
totalItems: number
}
export const PaginationBar = (props: Props) => {
// same code as above but no useEffect or useState
}
Now you have your own flexible pagination component. See here: https://codesandbox.io/s/eager-hermann-pjdt3?file=/src/App.js
You use it like this:
<Pagination
onNext={onNext}
onPrev={onPrev}
total={total}
pageNo={pageNo}
pageSize={10} />
Hope this helps!
React pagination come with minimum styling , anytime you can import demo css from github page
https://github.com/AdeleD/react-paginate/tree/master/demo/styles
in your component or
creating a styled component and customize your pagination all classes already include in your HTML like .active .first .last
or you can create custome styles for that class and append on your main.css

The Dialog component is not closing correctly

I have a problem with the React.js Dialog component which contains a list of items. There is also an overlay in the Dialog. It closes automatically when the user clicks on it. But the scenario is something different. The dialog also includes a list of items that have some external links wrapped around the <a> element and some with the <div>.
But the method of closing the dialog is not working properly. The Dialog automatically closes when I click inside any list item.
Please see this:
My goal was to close the dialog whenever the user clicked on the overlay or whenever the user clicked on the list item wrapped with the <a> element. Otherwise, it should not be closed.
I still can't figure out What is the correct approach to tackle this issue?
CodeSandbox link
App.js
import React, { useState } from 'react';
import Dialog from './Dialog';
import './App.css';
const App = () => {
const [isOpen, setIsOpen] = useState(false);
const onClickHandler = (isFalse) => {
if (!isFalse) {
setIsOpen(false);
} else {
setIsOpen(!isOpen);
}
};
return (
<div>
<button type="button" onClick={onClickHandler}>
Open Dialog
</button>
<Dialog isOpen={isOpen} onClick={onClickHandler} />
</div>
);
};
export default App;
Dialog.js
import React from 'react';
const Dialog = (props) => {
const { isOpen, onClick } = props;
const onCloseHandle = () => {
onClick(false);
};
return (
<div
className={isOpen ? 'dialog-wrap open' : 'dialog-wrap'}
onClick={onCloseHandle}
>
<div className="dialog">
<ul className="dialog-list">
<li>
<a
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
React.js
</a>
</li>
<li>
<a
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Another Link
</a>
</li>
<li>
<div>Should Not Close onClick</div>
</li>
<li>
<div>Should Not Close onClick</div>
</li>
</ul>
</div>
</div>
);
};
export default Dialog;
App.css
*,:before,:after {
box-sizing: border-box;
}
.dialog-wrap.open {
display: flex;
}
.dialog-wrap {
display: none;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 999;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding: 16px;
background-color: rgba(0,0,0,0.66);
}
#media (min-width: 640px) {
.dialog-wrap {
padding: 48px 32px;
}
}
#media (min-width: 1024px) {
.dialog-wrap {
padding-left: 40px;
padding-right: 40px;
}
}
.dialog {
position: relative;
margin: auto;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 12px 16px rgba(0, 0, 0, 0.08);
border-radius: 4px;
width: 500px;
}
.dialog-list {
margin-bottom: 0;
padding-left: 0;
color: #333;
list-style: none;
}
.dialog-list > li {
border-bottom: 1px solid #eee;
padding: 24px;
}
.dialog-list > li > a {
color: #333;
display: block;
text-decoration: none;
}
.dialog-list > li > div {
cursor: pointer;
}
in this situation, I would create a .dialog-background element and give onCloseHandle to that.
I also hive my a elements the onCloseHandle as onClick prop as well
If you do not want to change your react tree you can decide that from the event like this:
<div
className={isOpen ? "dialog-wrap open" : "dialog-wrap"}
onClick={(e) => {
if (!e.target.closest('.dialog') || e.target.closest('a')) {
onClick(false)
}
}}
/>
I think your click event is propagating up the elements, and triggering onCloseHandle on your .dialog-wrap.
The simplest solution to this would be to use Event.stopPropagation() on the <div className="dialog">
E.g.
<div className="dialog" onClick={ e => e.stopPropagation() }>
(React technically uses "synthetic events", but they still include a stopPropagation option as long as it's being interacted with inside React)

React JS shopping cart add functions

Hi guys and privet from Russia :)
I am trying to build a shopping cart but struggling to add certain functionalities by using React JS only (not redux or node)
This is my code so far:
App.js
import React from "react";
import Navbar from "./components/Navbar";
import Home from "./components/Home";
import "./App.css";
function App() {
return (
<div className="App">
<Navbar />
<Home />
</div>
);
}
export default App;
Home.js*components*
import React, { useState } from "react";
const Home = () => {
const [basketNumbers, setBasketNumbers] = useState(0);
const addToBasket = () => {
setBasketNumbers(setBasketNumbers + 1);
};
return (
<div className="container">
<div className="image">
<img
src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTVWhIi-Mq_A6psrTdfOuElSh7p8y5AzevI7cLWnSLAr0BkQlT0&usqp=CAU"
alt="A green Beautiful dress"
/>
<h3>Green Dress</h3>
<h3>15€</h3>
<a onClick={addToBasket} className="addToCart cart1" href="#">
Add To Cart
</a>
</div>
<div className="image">
<img
src="data:image/jpeg;base64,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"
alt="A beautiful Hot Pink Dress"
/>
<h3>Pink Dress</h3>
<h3>350€</h3>
<a onClick={addToBasket} className="addToCart cart2" href="#">
Add To Cart
</a>
</div>
<div className="image">
<img
src="https://m.media-amazon.com/images/I/71dAgPUbwKL._SR500,500_.jpg"
alt="A beautiful Black Dress"
/>
<h3>Black Dress</h3>
<h3>400€</h3>
<a onClick={addToBasket} className="addToCart cart3" href="#">
Add To Cart
</a>
</div>
<div className="image">
<img
src="https://ae01.alicdn.com/kf/He938e0d8636a44c9a4440109bf998d67j/Off-Shoulder-Elegant-Backless-Long-Royal-Blue-Evening-Dresses-2019-Lace-Up-Party-Maxi-Dress-Formal.jpg_640x640q70.jpg"
alt="A Beautiful Blue Dress"
/>
<h3>Blue Dress</h3>
<h3>250€</h3>
<a onClick={addToBasket} className="addToCart cart 4" href="#">
Add To Cart
</a>
</div>
<div className="image">
<img
src="https://ae01.alicdn.com/kf/HTB1Lpp9XAPoK1RjSZKbq6x1IXXaf/Summer-Sexy-Spaghetti-Strap-Ruffle-Women-Dress-Backless-A-Line-Formal-Evening-Party-Dress-Short-Front.jpg_640x640q70.jpg"
alt="A beautiful Red Dress"
/>
<h3>Red Dress</h3>
<h3>150€</h3>
<a onClick={addToBasket} className="addToCart cart5" href="#">
Add To Cart
</a>
</div>
<h1>Current Number In Cart {basketNumbers}</h1>
</div>
);
};
export default Home;
Navbar.js *components*
import React from "react";
function Navbar() {
return (
<header>
<div className="overly" />
<nav>
<h2>Shop</h2>
<ul>
<li>
Home
</li>
<li classname="cart">
{" "}
<a href="#">
<ion-icon name="cart" />
Cart<span> 0 </span>
</a>
</li>
</ul>
</nav>
</header>
);
}
export default Navbar;
This is my CSS just in case:
li a {
padding: 5px;
background-color: white;
text-decoration: none;
}
.cart ion-icon {
vertical-align: bottom;
font-size: 20px;
padding-right: 5px;
}
.cart a {
background-color: royalblue;
color: white;
cursor: pointer;
text-decoration: none;
}
.container {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin-top: 50px;
padding-bottom: 100px;
}
.img {
margin-right: 20px;
margin-left: 20px;
position: relative;
overflow: hidden;
}
.addToCart {
position: absolute;
width: 100%;
background-color: darkgray;
transition: all 0.3s ease-in-out;
opacity: 0;
cursor: pointer;
text-align: center;
}
.image:hover .cart1,
.image:hover .cart2,
.image:hover .cart3,
.image:hover .cart4,
.image:hover .cart5 {
bottom: 50px;
opacity: 1;
padding: 10px;
text-decoration: none;
}
What I would like to add to this code:
Add to cart click will add the product to the cart and not just show it on the bottom part of the page
Add a total which changes whenever a new item is added to the cart
Add a free shipping for a car above 500 EUR, else having a message saying you're not entitled to a free shipping.
Thank you so much :)
well i can't actually do all what you want bcs... you shouldn't actually ask people here to add those features for you bcs i think they take so much lines, you should try to add them yourself and then if your code doesnt work, you just ask here, anyways i found a mistake in your code and i'm gonna correct it for ya:
Home.jscomponents
import React, { useState } from "react";
const Home = () => {
const [basketNumbers, setBasketNumbers] = useState(0);
const addToBasket = () => {
setBasketNumbers(oldBasketNum => oldBasketNum + 1); //this is the correct way to update the state on click, bcs u wrote setBasketNumbers +1 which won't work
};
return (//the rest of your code here)
Hope this was helpfull, thanks
**
Edit:
**
You also should add more components to save you some space in your render method like this:
Item component:
import React from "react";
const Item = (props) => {
return (
<div className="image">
<img src={props.img} alt={props.alt} />
<h3>props.name</h3>
<h3>props.price</h3>
<a onClick={props.addToBasket} className="addToCart cart1" href="#">
Add To Cart
</a>
</div>
);
};
export default Item;
Home.js component:
import React, { useState } from "react";
import Item from "./item.js";
const Home = () => {
const [basketNumbers, setBasketNumbers] = useState(0);
const addToBasket = () => {
setBasketNumbers((oldBasketNum) => oldBasketNum + 1); //this is the correct way to update the state on click, bcs u wrote setBasketNumbers +1 which won't work
};
return (
<div className="container">
<Item name="" price="" img="" alt="" /> //you fill this props as you want
the items to be
<Item name="" price="" img="" alt="" /> //you could also make this more
dynamic using arrays
</div>
);
};

Resources