How can I do conditional rendering on a styled component? - reactjs

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}>

Related

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>
)
}

Why does my overlay not transition while rerendering?

I'm trying to transition a simple overlay if one of four thumbnails is clicked. My idea was to toggle the overlays opacity within the inline style of the element like this..
<div className='product-thumbnail-overlay' style={selectedThumbnail === id ? { opacity: 1 } : { opacity: 0 }}></div>
This is working until I wrap this code in a react function component to avoid repetitions of my code.
HTML
import { useState, useEffect } from 'react';
import './Product.scss';
import ProductImage1 from '../assets/images/image-product-1.jpg';
import ProductImage2 from '../assets/images/image-product-2.jpg';
import ProductImage3 from '../assets/images/image-product-3.jpg';
import ProductImage4 from '../assets/images/image-product-4.jpg';
import ProductThumbnail1 from '../assets/images/image-product-1-thumbnail.jpg';
import ProductThumbnail2 from '../assets/images/image-product-2-thumbnail.jpg';
import ProductThumbnail3 from '../assets/images/image-product-3-thumbnail.jpg';
import ProductThumbnail4 from '../assets/images/image-product-4-thumbnail.jpg';
const Product = () => {
const [selectedThumbnail, setSelectedThumbnail] = useState(1);
const getProductThumbnailById = (id) => {
// get the imported product thumbnail
};
const ProductThumbnail = ({ id }) => {
return (
<div className='product-thumbnail-container' onClick={() => setSelectedThumbnail(id)}>
<img src={getProductThumbnailById(id)} alt='thumbnail of product' className='product-thumbnail' />
<div
className='product-thumbnail-overlay'
style={selectedThumbnail === id ? { opacity: 1 } : { opacity: 0 }}
></div>
</div>
);
};
return (
<main>
<div className='product-images'>
<img src={ProductImage1} alt='product' className='product-image' />
<div className='product-thumbnails'>
<ProductThumbnail id={1} />
<ProductThumbnail id={2} />
<ProductThumbnail id={3} />
<ProductThumbnail id={4} />
</div>
</div>
<div className='product-details'></div>
</main>
);
};
export default Product;
important SCSS
.product-thumbnail-container {
position: relative;
flex: 20.5%;
cursor: pointer;
.product-thumbnail {
display: block;
max-width: 100%;
border-radius: variables.$br;
}
.product-thumbnail-overlay {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(255, 255, 255, 0.6);
border: 2px solid variables.$clr_prim_orange;
border-radius: variables.$br;
transition: all 2000ms ease-in-out;
}
}
Codepen with what im trying to accomplish (but with repetitions of code): https://codepen.io/Sandhexer/pen/JjLrZOQ?editors=0110
Codepen with current code: https://codepen.io/Sandhexer/pen/gOeGKpP?editors=0110
I think that the rerendering causes the element not to transition because the opacity doesnt really change. Is this right and does anyone know a solution or good workaround for this problem?

React do I need a hook for each component?

Problem Description
I have faced this issue multiple times and am not sure what is the best approach. Say I have 3+ components how can I have a state tracker for each of them? Do I need n useState() hooks for n components?
In this example, I want to change the image displayed with onMouseOver(). The way I did it, the hook state is applied to all the images, which is not what I desire to do.
Restrictions
I want to have eventually a custom drop-down menu with onClick() particular to the image folder. So in that sense, I need an individual state tracker for each component?
Code and Snippet
const openFolder = "https://i.postimg.cc/V6L7kBCV/folder-Open.png";
const closedFolder = "https://i.postimg.cc/hG0yn3fm/folder-Closed.png"
function App() {
const [image, setImage] = React.useState(closedFolder);
const handleMouseOver = () => {
setImage(openFolder);
}
const handleMouseLeave = () => {
setImage(closedFolder);
}
return (
<div className="window">
<div className="slider">
<div className="container">
{buildLatexFolder(image,handleMouseOver,handleMouseLeave)}
</div>
</div>
</div>
);
}
const buildLatexFolder = (image,handleMouseOver,handleMouseLeave) => {
const courseNames = [
'A', 'B', 'C', 'D', 'E', 'F'
//and many more other
]
var folders = courseNames.map((value, index) => {
return (
<div className="folderContainer">
<span>{value}</span>
<div onMouseEnter={() => {handleMouseOver()}} onMouseLeave={() => {handleMouseLeave()}}>
<img src={image} width="130"/>
</div>
</div>
);
});
return folders;
}
ReactDOM.render(<App />, document.querySelector("#app"));
.window {
width: 500px;
height: 130px;
display: flex;
align-items: center;
margin-left: auto;
margin-right: auto;
}
.slider {
border-radius: 0px 0px 16px 16px;
background-color: #1F1F1F;
color: #ffffff;
overflow: hidden;
float: right;
}
.container {
display: flex;
width: 700px;
height: 130px;
margin-top: 10px;
align-items: center;
text-align: center;
}
.folderElement {
margin-left: 12px;
margin-right: 15px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>
with JSFiddle here
What I Have Tried
Previously, when faced with this problem I would just make, say, 3 hooks for my 3 components and handle the logic this way. But now I have a large number of components and don't know what is the best approach.
I have searched online 'React Should I have a hook for each component', 'How many hooks to have for components', and so on and so forth but the search results are inaccurate with what I am trying to find, or for that matter my question is inaccurate. I don't know how to proceed.
Does anyone know how I can fix this issue?
You need to have component modularization in your application. Then you can have a single CourseFolder which can be used as a child component resides in your parent component which is App. Using map, you can view multiple child components having different courseDetails inside them.
Refer the following code-snippets I created to solve your issue.
App.js
import React from "react";
import CourseFolder from "./CourseFolder";
// import "./folderStyles.css"; /* kept the styles posted in the question */
const courseNames = [
"A",
"B",
"C",
"D",
"E",
"F",
//and many more other
];
function App() {
return (
<div className="window">
<div className="slider">
<div className="container">
{courseNames.map((value, index) => (
<CourseFolder value={value} key={index} />
))}
</div>
</div>
</div>
);
}
export default App;
Then create the child component as follows.
CourseFolder.js
import React from "react";
const openFolder = "https://i.postimg.cc/V6L7kBCV/folder-Open.png";
const closedFolder = "https://i.postimg.cc/hG0yn3fm/folder-Closed.png";
function CourseFolder(props) {
const { value, key } = props;
const [image, setImage] = React.useState(closedFolder);
const handleMouseOver = () => {
setImage(openFolder);
};
const handleMouseLeave = () => {
setImage(closedFolder);
};
return (
<div className="folderContainer" key={key}>
<span>{value}</span>
<div
onMouseEnter={() => {
handleMouseOver();
}}
onMouseLeave={() => {
handleMouseLeave();
}}
>
<img src={image} width="130" alt="alternative" />
</div>
</div>
);
}
export default CourseFolder;
Hope this would be helpful to solve your issue.

Carousel in React using Flickity

Is it possible for this code to work in React? I tried to use the .js file provided, however it fails. Could you please give me some tips on how to create such carousel in React?
// external js: flickity.pkgd.js
/* external css: flickity.css */
* {
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
body { font-family: sans-serif; }
.gallery {
background: #EEE;
}
.gallery-cell {
width: 66%;
height: 200px;
margin-right: 10px;
background: #8C8;
counter-increment: gallery-cell;
}
/* cell number */
.gallery-cell:before {
display: block;
text-align: center;
content: counter(gallery-cell);
line-height: 200px;
font-size: 80px;
color: white;
}
<p><code>wrapAround: true</code></p>
<!-- Flickity HTML init -->
<div class="gallery js-flickity"
data-flickity-options='{ "wrapAround": true }'>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
</div>
this is how you would implement it in react :
import Flickity from 'react-flickity-component'
const flickityOptions = {
initialIndex: 2
}
function Carousel() {
return (
<Flickity
className={'carousel'} // default ''
elementType={'div'} // default 'div'
options={flickityOptions} // takes flickity options {}
disableImagesLoaded={false} // default false
reloadOnUpdate // default false
static // default false
>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
<div class="gallery-cell"></div>
</Flickity>
)
}
No need for a wrapper. You just need to install flickity as a dependency, and you can import it dynamically. Here's how to use Flickity in React or Next.js:
export default function Carousel() {
useEffect(() => {
initFlickity();
}, []);
const carousel = useRef(null);
async function initFlickity() {
if (typeof window !== 'undefined' && carousel.current) {
const Flickity = (await import('flickity')).default;
new Flickity(carousel.current, {
lazyLoad: true,
wrapAround: true,
autoPlay: true,
});
}
}
return (
<div ref={carousel} className="w-full h-[600px] sm:w-[560px] sm:h-auto mx-auto relative">
<div>
<img src="/images/slide-1.jpg" />
</div>
<div>
<img src="/images/slide-2.jpg" />
</div>
</div>
);
}
Make sure you set dimensions for your containing element.

How to set className to div in ReactJS using functional component

I have following code:
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [border, setBorder] = useState(false);
return (
<div className="App">
<div className="SectionTitleItem">Claimers</div>
<div className="SectionTitleItem">Resources</div>
</div>
);
}
CodeSandbox
How can I set the border-bottom only for the active item?
App.js
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [active, setActive] = useState(true);
return (
<div className="App">
<div onClick={() => setActive(true)} className={`SectionTitleItem${active ? " active" : ""}`}>Claimers</div>
<div onClick={() => setActive(false)} className={`SectionTitleItem${!active ? " active" : ""}`}>Resources</div>
</div>
);
}
styles.css
.App {
font-size: 18px;
margin: 40px 0 32px 0;
display: flex;
}
.SectionTitleItem {
margin-left: 50px;
}
.SectionTitleItem.active {
border-bottom: 2px solid red;
}
Perhaps something like
export default function App() {
const [active, setActive] = useState(null);
const getItemClassName = (name) => {
if (name === active) {
return "SectionTitleItem active";
}
return "SectionTitleItem";
};
return (
<div className="App">
<div
onClick={() => setActive("claimers")}
className={getItemClassName("claimers")}
>
Claimers
</div>
<div
onClick={() => setActive("resources")}
className={getItemClassName("resources")}
>
Resources
</div>
</div>
);
}
.App {
font-size: 18px;
margin: 40px 0 32px 0;
display: flex;
}
.SectionTitleItem {
margin-left: 50px;
}
.SectionTitleItem.active {
border-bottom: 2px solid red;
}

Resources