Want to target only one div at a time, the div which is hovered but not the other sibling div in ReactJS? - javascript

I am having a unique scenario but I am unable to understand this.
When I hover on one DIV then it selects both the sibling DIVS.
I do not want this behaviour.
I want to select only the DIV which is being hovered.
How can I achieve this in ReactJS ?.
The working code is shown below.
App.js
import React,{useState} from 'react';
import "./App.css";
const App = () => {
const [hover, setHover] = useState(false);
const texts = ["Arjun", "Andy"];
let cclass = hover ? "item itemHover":"item";
return (
<div className="wrapper">
{
texts.map((t, i) => (
<div className={cclass} key={i} onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}>
{t}
</div>
))
}
</div>
)
}
export default App;
App.css
.wrapper{
width: 60%;
margin: 10rem auto;
border: 1px solid;
display: flex;
}
.item{
width: 50%;
border: 1px solid grey;
height: auto;
padding: 2rem 3rem;
}
.itemHover{
background: grey;
}

The hover state in App is common for both divs. To make it work you need to
have hover state for each div separate. For this, create a new component TextDiv
import React, {useState} from "react";
import "./styles.css";
export default function TextDiv({t}) {
const [hover, setHover] = useState(false);
let cclass = hover ? "item itemHover":"item";
return (
<div className={cclass} onMouseEnter={() => setHover(true)}
onMouseLeave={() => setHover(false)}>
{t}
</div>
)
}
and change App.js file
import React, {useState} from "react";
import TextDiv from './TextDiv'
import "./styles.css";
export default function App() {
const texts = ["Arjun", "Andy"];
return (
<div className="wrapper">
{
texts.map((t, i) => (
<TextDiv t={t} key={i}/>
))
}
</div>
)
}

Can you do it with CSS? It's very simple with CSS. Just add this:
.item:hover{
background: grey;
}

Related

Unable to extend react component in styled-component

I am trying to extent react component in styled-component and trying to add custom style on extended component but unable to see the style changes that I am applying
I have created a button component in /src/newbutton.js with following code
import styled from "styled-components";
const Button = styled.button`
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
export const NewButton = ({ className, children }) => {
return (
<Button primary>Primary</Button>
)
}
And extending and creating another button component with custom style in /src/custom-button.js with following code
import styled from "styled-components";
import { NewButton } from './button'
const ButtonWrapper = styled(NewButton)`
width: 100%;
color: red
`;
const ExtendedButton = ({ className, children }) => {
return (
<ButtonWrapper />
)
}
I have added the custom style like width: 100% & color: red but it is not applying on ExtendedButton. Infect colour and width is same as NewButton
You need to pass a className to your NewButton in order to customize it, using styled-components.
Styled components works by creating a unique className that associated with a component and its CSS.
export const NewButton = ({ className, children }) => {
return (
<Button className={className} primary>Primary</Button>
)
}
I am posting the complete working code for future reference based on #Flat Globe solution. And it is working fine as expected.
I have modified the Button component code just by adding className in /src/newbutton.js with following code
import styled from "styled-components";
const Button = styled.button`
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};
font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;
export const NewButton = ({ className, children }) => {
return (
<Button primary className={className}>Primary</Button>
)
}
I have also modified the extended-button code by just passing the className in /src/custom-button.js. check the full code below
import styled from "styled-components";
import { NewButton } from './button'
const ButtonWrapper = styled(NewButton)`
width: 100%;
color: red
`;
const ExtendedButton = ({ className, children }) => {
return (
<ButtonWrapper className="extended-button"/>
)
}

How to make the label that wraps a button clickable too in React

Having the following components:
<CheckboxGroupLabel htmlFor={option.label}>
<FormCheckbox
onClick={() => onChange}
key={option.label}
defaultChecked={defaultChecked}
{...rest}
/>
{option.value}
</CheckboxGroupLabel>
Their styled components are:
import styled from 'styled-components';
import * as Checkbox from '#radix-ui/react-checkbox';
export const CheckboxGroupLabel = styled.label`
background-color: red;
display: flex;
width: 100%;
margin: 18px;
line-height: 20px;
cursor: pointer;
width: 100px;
`;
export const StyledCheckboxRoot = styled(Checkbox.Root)`
button {
all: unset;
}
`;
So the checkbox is inside label but only checkbox is clickable, I would like to make the whole label clickable.
Is there a way to do that?
Have you tried just moving onClick into CheckboxGroupLabel?
https://codesandbox.io/s/label-onclick-3ebkbi
import "./styles.css";
import * as Checkbox from "#radix-ui/react-checkbox";
import { CheckIcon } from "#radix-ui/react-icons";
export default function MyComponent() {
const onLabelClick = () => {
console.log("clicked label");
};
return (
<div>
<label onClick={onLabelClick} htmlFor="mycheckbox">
<Checkbox.Root className="checkbox" defaultChecked id="mycheckbox">
<Checkbox.Indicator className="indicator">
<CheckIcon />
</Checkbox.Indicator>
My checkbox label
</Checkbox.Root>
</label>
</div>
);
}

Can't use imported randomColor function in react component

I am trying to build a random color generater with the randomcolor npm package. When a button is clicked a div should change its color randomly. But react doesn't let me use the randomColor function inside of my reatc component and I don't know why.
import './App.css';
import randomColor from 'randomcolor';
import { useState } from 'react';
import styled from 'styled-components';
function App() {
const [randomColor, setRandomColor] = useState('white');
const Generated = styled.div`
background-color: ${randomColor};
transition: all 0.3s;
padding: 4rem 8rem;
border-radius: 10px;
`;
return (
<Container className="App">
<Button
onClick={() => setRandomColor(randomColor({luminosity: "random", hue:"random"}))}
className="generate"
>
Generate
</Button>
<Generated>Generated Color: {randomColor}</Generated>
</Container>
);
}
export default App;
Does anyone know why it says "randomColor" is declared but never used and why I can't use it in my component?
you have silly mistake, change your randomColor and SetRandomColor name javascript confused by the same name with randomColor() function is this correct of your code :
import './App.css';
import randomColor from 'randomcolor';
import { useState } from 'react';
import styled from 'styled-components';
function App() {
const [randomColor2, setRandomColor2] = useState('white');
const Generated = styled.div`
background-color: ${randomColor};
transition: all 0.3s;
padding: 4rem 8rem;
border-radius: 10px;
`;
return (
<Container className="App">
<Button
onClick={() => setRandomColor2(randomColor({luminosity: "random", hue:"random"}))}
className="generate"
>
Generate
</Button>
<Generated>Generated Color: {randomColor2}</Generated>
</Container>
);
}
export default App;

import export styled component reactjs

i want to split page between styling and app
example
in page style.js
import styled from "styled-components";
//i dont know how to export all const
export const Container = styled.div`
display: flex;
flex-direction: row;
`;
export const Sidebar = styled.div`
width: 20%;
height: 100%;
background-color: #f9f9f9;
`;
and in page app.js
import * as All from "./style.js"
//i dont know, how to import all const in style.js
function App(){
return(
<Container>
<Sidebar>
</Sidebar>
</Container>
)}
how to export and import all const when const in style.js there are so many?
another option you can export like this :
import styled from "styled-components";
const Container = styled.div`
display: flex;
flex-direction: row;
`;
const Sidebar = styled.div`
width: 20%;
height: 100%;
background-color: #f9f9f9;
`;
export {Container,Sidebar}
and you can import like this :
import { Container,Sidebar } from './style';
function App() {
return (
<Container>
<Sidebar>
</Sidebar>
</Container>
);
}
There is a beautiful way to do that. This way also let you know which component is styled-component or single component.
// style.js
export const Styled = {
Container: styled.div`
display: flex;
flex-direction: row;
`,
Sidebar: styled.div`
width: 20%;
height: 100%;
background-color: #f9f9f9;
`,
}
import { Styled } from './style';
function App() {
return (
<Styled.Container>
<Styled.Sidebar>
</Styled.Sidebar>
</Styled.Container>
);
}
Dae Hyeon Mun's approach is great, but you can simplify it further and avoid having to refactor your styles.js file by using a wildcard import, which essentially creates a module object so you don't have to!:
// style.js
export const Container = styled.div`
...
`;
export const Sidebar = styled.div`
...
`;
// app.js
import * as Styled from './style';
function App() {
return (
<Styled.Container>
<Styled.Sidebar>
</Styled.Sidebar>
</Styled.Container>
);
}
More details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules#creating_a_module_object
You can use "export const" like you already did for exporting. The simplest way to import those const is:
import * as styled from "./style.js"
//this will import all 'export const' containing 'styled' from "./style.js"
function App(){
return(
<Container>
<Sidebar>
</Sidebar>
</Container>
)}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

My component re-render after i try to search for an element in a useState array

I am currently building a React project, so I made a search Input and when I type something in that Input field my hole component re-renders causing an API recall and deleting the text in my Input. I tried merging both the search component with Home component and the same problem appears.
I want my component to call the api only one time, and I am trying to filter the response depending on the input type.
please help!!
Here is my Home component:
import { useContext, useEffect, useState } from 'react';
import styled from 'styled-components';
import CountryThumb from '../Components/CountryThumb';
import ThemeContext from '../Components/ColorPalette';
import { Themes } from '../Components/ColorPalette';
import Search from '../Components/Search';
import Filter from '../Components/Filter';
const Grid = styled.main`
width: 100%;
display: grid;
grid-template-columns: repeat(4, 1fr);
column-gap: 60px;
row-gap: 40px;
#media (max-width: 375px) {
grid-template-columns: repeat(1, 1fr);
}
`;
export default function Home() {
const [Countries, setCountries] = useState([]);
const [SearchTerms, setSearchTerms] = useState('');
const { Theme } = useContext(ThemeContext);
const style = Theme == 'light' ? Themes.light : Themes.dark;
useEffect(() => {
getCountries();
}, []);
const Main = styled.main`
display: flex;
flex-wrap: wrap;
padding: 20px 100px;
background-color: ${Theme == 'light' ? style.background : style.background};
#media (max-width: 375px) {
padding: 40px 25px;
}
`;
const getCountries = () => {
axios
.get('https://restcountries.eu/rest/v2/all')
.then((res) => setCountries(res.data))
.catch((err) => console.log(err));
};
return (
<>
<Main>
<Search handleSearch={(e) => setSearchTerms(e.target.value)} />
<Filter />
<Grid>
{Countries.slice(0, 12)
.filter((e) => {
if (SearchTerms == '') {
return e;
} else if (
e.name.toLowerCase().includes(SearchTerms.toLowerCase())
) {
return e;
}
})
.map((e) => (
<CountryThumb props={e} />
))}
</Grid>
</Main>
</>
);
}
And here is my Search component:
import { useContext, useState } from 'react';
import styled from 'styled-components';
import ThemeContext, { Themes } from './ColorPalette';
function Search({ handleSearch }) {
const { Theme } = useContext(ThemeContext);
const style = Theme == 'light' ? Themes.light : Themes.dark;
const Svg = styled.svg`
width: 24px;
height: 24px;
color: ${style.text};
`;
const Wrapper = styled.div`
background-color: ${style.element};
border-radius: 5px;
box-shadow: 0 5px 10px ${style.shadow};
display: flex;
align-items: center;
padding: 0 20px;
margin: 40px 0;
`;
const CInput = styled.input`
border: none;
outline: none;
padding: 15px 120px 15px 20px;
font-size: 1rem;
color: ${style.text};
background: none;
`;
return (
<>
<Wrapper>
<Svg
xmlns='http://www.w3.org/2000/svg'
class='h-6 w-6'
fill='none'
viewBox='0 0 24 24'
stroke='currentColor'
>
<path
strokeLinecap='round'
strokeLinejoin='round'
strokeWidth='2'
d='M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z'
/>
</Svg>
<CInput
type='text'
name='Search'
onInput={handleSearch}
placeholder='Search for a country ...'
/>
</Wrapper>
</>
);
}
export default Search;
Whenever you change anything in state your component will rerender so it is normal behaviour. However you have dependency array in useEffect that calls api so this function should run only one time, maybe you didnt have array before and forgot to save.

Categories

Resources