conditional operator in react not working with css - javascript

In my task component on the parent div I am trying to make it so when reminder is set to true it adds a "reminder" class to the div, which just adds a border left. If reminder is set to false the "reminder" class will not be added.
I have checked and on double click the reminder does toggle between true and false so I know that works.
const Task = ({ task, onDelete, onToggle }) => {
return (
<div
className={`task ${task.reminder ?
'reminder' : ''}`}
onDoubleClick={() => onToggle(task.id)} className="task">
<h3>{task.text} <FaTimes
onClick={() => onDelete(task.id)}
style={{
color: "red", cursor: "pointer"
}} />
</h3>
<p>{task.day}</p>
</div>
)
}
export default Task
.task {
background: #f4f4f4;
margin: 5px;
padding: 10px 20px;
cursor: pointer;
}
.task.reminder {
border-left: 5px solid green !important;
}

onToggle , you are not passing task.remainder , how will task.remainder changes ?
Please pass task.remainder in onToggle function
Your code must look like this .
<div className={task ${task.reminder ?'reminder' : ''}} onDoubleClick={() => onToggle(task.remainder)} className="task">

I think you are adding className 2 times in div element remove 2nd one then you will get your result. Actually, your logic is correct but you did that small mistake adding className 2 times.
Btw, there is 2 ways to implement that logic-
className={`${task.reminder ? 'task reminder' : 'task'}`}
className={`task ${task.reminder ? 'reminder' : ''}`}

Related

Trying to convert a custom vanilla javascript dropdown menu for use in React

I'm pretty new with React (and JS in general for that matter), but I'm trying to get a dropdown menu (that will eventually work like a query selector for a search bar) to work with some custom styling.
I found a perfect solution at w3schools with inline javascript. The problem is I can't seem to get it to work in a react application. Maybe it's as simple as some syntax changes between vanilla JS and React, but so far it doesn't work. Any advice would be appreciated.
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_custom_select
Blake.
So React components are typically built in a much different way to how this example would be built. React requires use of State to update the interface and we don't use tags.
I would recommend, instead of spending much time converting this example, finding an existing React drop-down package that works the same way.
This is a great existing package for creating React drop-downs and I have used it myself in the past. Follow the guide on there and you'll have it implemented in no time.
Hope this helped explain it and welcome to the React community!
Of course, we can use any available select item library out there. One of my favourites is headles.ui.
But if we want to master react, it is better to learn to make it from scratch.
So, Let's do it with React Way to make it works.
First of all, we need to keep in mind that React deals with state. So, we will use state to convert your example into React app.
Here, we will not use plain <select> & <option> tag since this is a Custom Select. The data we put inside an selectItems array:
const selectItems = [
"Audi",
"BMW",
"Citroen",
"Ford",
"Honda",
"Jaguar",
"Land Rover",
"Mercedes",
"Mini",
"Nissan",
"Toyota",
"Volvo",
];
Next, we define two state in our component which are active state and selected state.
// this state will be used in conditional rendering of our list items
// the value is boolean and the default is false (not active)
const [active, setActive] = useState(false);
// this state will keep our selected item
const [selected, setSelected] = useState("Select car:");
To open and close the List Items, we need to define a toggle method, that will toggle the active state by negating the previous state:
const toggle = () => setActive((prevState) => !prevState);
And whenever the user click a List Item, the element will set the selected state with the element item value, and hide the List Items by calling the toggle method:
const handleItemClick = (item) => {
setSelected(item);
toggle();
};
In order to render the selected item and the list items, we need to create two sections:
return (
<div>
...
{/* at onClick listener we pass toggle method */}
<div className="select-selected" onClick={toggle}>
// Selected Item section
</div>
<div className="select-items">
// Select Items section
</div>
</div>
)
At Selected Item, we define conditional class name and add selected state. The className will have value select-selected select-arrow-active if state active value is true and will be select-selected only if otherwise.
return (
...
<div className={`select-selected ${active ? 'select-arrow-active' : ''}`} onClick={toggle}>
{selected}
</div>
)
And lastly, we render the List items by using javascript map method:
return (
...
<div className="select-items">
{/* we render list items only when active state is true */}
{active && selectItems.map((item,i) => {
return (
<div
key={i}
onClick={() => handleItemClick(item)}
{/* when the selected item equal to the item then use "same-as-selected" className */}
className={`${item === selected ? "same-as-selected": ""}`}
>
{item}
</div>
)
})}
</div>
...
)
And finally, this is the complete code. Minimal example but at least have followed the given vanilla javascript example.
You can see our select item component in action by clicking the blue Run code snippet button below.
const { useState } = React;
const selectItems = [
"Audi",
"BMW",
"Citroen",
"Ford",
"Honda",
"Jaguar",
"Land Rover",
"Mercedes",
"Mini",
"Nissan",
"Toyota",
"Volvo",
];
function App() {
const [active, setActive] = useState(false);
const [selected, setSelected] = useState("Select car:");
const toggle = () => setActive((prevState) => !prevState);
const handleItemClick = (item) => {
setSelected(item);
toggle();
};
return (
<div>
<h2>Custom Select</h2>
<div className="custom-select">
<div className={`select-selected ${active ? 'select-arrow-active' : ''}`} onClick={toggle}>
{selected}
</div>
<div className="select-items">
{active && selectItems.map((item,i) => {
return (
<div
key={i}
onClick={() => handleItemClick(item)}
className={`${item === selected ? "same-as-selected": ""}`}
>
{item}
</div>
)
})}
</div>
</div>
</div>
)
}
ReactDOM.render(<App />, document.querySelector('.react'));
.custom-select {
position: relative;
font-family: Arial;
color: #ffffff;
width: 200px;
}
.select-selected {
background-color: DodgerBlue;
padding: 8px 16px;
cursor: pointer;
}
.select-selected:after {
position: absolute;
content: "";
top: 14px;
right: 10px;
width: 0;
height: 0;
border: 6px solid transparent;
border-color: #fff transparent transparent transparent;
}
.select-selected.select-arrow-active:after {
border-color: transparent transparent #fff transparent;
top: 7px;
}
.select-items div,.select-selected {
color: #ffffff;
padding: 8px 16px;
border: 1px solid transparent;
border-color: transparent transparent rgba(0, 0, 0, 0.1) transparent;
cursor: pointer;
user-select: none;
}
.select-items {
position: absolute;
background-color: DodgerBlue;
top: 100%;
left: 0;
right: 0;
z-index: 99;
}
.select-items div:hover, .same-as-selected {
background-color: rgba(0, 0, 0, 0.1);
}
<script crossorigin src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-table#7.8.0/dist/react-table.development.js"></script>
<div class='react'></div>

How to change a div border color when clicked?

Working on a react/typescript project, I have a div and want to replace the border color and width of a div when it's clicked:
<div
className="showroom-card "
onClick={() => setSelection({ showroom: 'Westchester' })}
>
I know it should be simple but I'm pretty new to this.
in javascript you can make but please describe more
div.style.border="1px solid #000";
With pure html/js it would be look like that:
.showroom-card {
width: 500px;
height: 300px;
background-color: yellow;
border: 2px solid red;
}
.selected {
border: 2px solid black;
}
<div
id="card1"
class="showroom-card"
onClick="(function(divId) {
targetDiv = document.querySelector(`#${divId}`)
targetDiv.classList.toggle('selected')
})('card1');return false;"
></div>
But in react you must use state of component to manipulate div's style. For example, you would use divToggled variable in state of your component to render border and manipulate its color. The handler function, named handleDivClick change state and component will be rerendered:
class YourComponent extends React.Component {
...
handleDivClick = () => {
this.setState(divToggled: !this.state.divToggled)
}
...
render() {
return (
<div
onClick={this.handleDivClick}
className={`showroom-card ${this.state.divToggled ? 'selected' : ''}`}
/>
)
}
}

conditional className convert to styled component

Im trying to learn and convert my project from css to styled component(https://styled-components.com/), at the moment i have converted all my other components except one component where i am stuck, checked others examples from stackoverflow but it was not same kind.
I have conditional class names
My question is how to convert InfoBox component to use styled component ? do i need to inject the styles through some kind of styled-component wrapper or thats not needed ?
english is not my mother language so could be mistaked
my code:
import React from 'react'
import "./InfoBox.css"
function InfoBox({ isRed, active, activetored, ...props }) {
return (
<div onClick={props.onClick}
className={`infoBox ${active && "infoBox--selected"}
${activetored && "infoBox--selectedtored"}
${isRed && "infoBox--red"} `} >
</div>
)
}
export default InfoBox
<div className="app__stats">
<InfoBox
isRed
active={typeofCase === "cases"}
onClick={(e) => setTypeofCase('cases')}
/>
<InfoBox
isGreen
active={typeofCase === "recovered"}
onClick={(e) => setTypeofCase('recovered')}
/>
<InfoBox
isRed
activetored={typeofCase === "deaths"}
onClick={(e) => setTypeofCase('deaths')}
/>
</div>
css is like this (you can put whatever):
. infoBox--selected {
border-top: 10px solid greenyellow;
}
. infoBox--selectedtored {
border-top: 10px solid red;
}
. infoBox--red {
border-color: darkblue;
}
One of the ideas behind styled-component is to avoid classnames.
Instead of setting the css by class, you have few options. the easiest one will probably be to use your props inside the css code, and change the style by it:
const InfoBox = styeld.div`
border-color: ${props => props.isRed ? 'darkblue' : 'black'};
border-top: ${props => props.active ? '10px solid greenyellow' : 'red'};
...
`;
this way, you don't need classnames (although it can be done with it too, obviously).
Now, instead of the div inside the component, use the InfoBox styled component we just wrote and you good to go.

Using styled component

I have a button which need to be styled using styled component. As I am new to react I need your help in getting button color change to green on success and blue on failure. Also I have class card-preview which need to have box shadow when I hover on it while using styled component .The below code will give you an idea what I am trying to do.
import styled from "styled-components";
const Button = styled.button`
border: none;
border-radius: 10px;
padding: 7px 10px;
font-size: 1.3rem;
background: ${(props) => (props.success ? "green" : "blue")};
color: white;
`;
const Cardlist = ({ cards, title }) => {
return (
<div className="card-list">
<h2>{title}</h2>
{cards.map((card) => (
<div className="card-preview" key={card.id}>
<h2>{card.name}</h2>
if({card.status}==='success')
<Button success>{card.status}</Button>
else
<Button pending>{card.status}</Button>
</div>
))}
</div>
);
};
export default Cardlist;
For the button and CSS I think what you have should be working, though it could be more DRY. The if-else isn't valid in JSX anyway. I'm also not sure what you do with the pending prop, but it appears to be the antithesis of the success "state".
const Button = styled.button`
border: none;
border-radius: 10px;
padding: 7px 10px;
font-size: 1.3rem;
background: ${(props) => (props.success ? "green" : "blue")};
color: white;
`;
...
{cards.map((card) => (
<div className="card-preview" key={card.id}>
<h2>{card.name}</h2>
<Button
success={card.status === 'success'}
pending={card.status !== 'success'} // <-- may not be necessary
>
{card.status}
</Button>
</div>
))}
To apply some style to the card-preview div you just need to convert that to a styled-component as well.
const CardPreview = styled.div.attrs(() => ({
className: "card-preview",
}))`
:hover { // <-- sometimes you need &:hover to get the parent node
// apply box-shadow and any other CSS rules here
}
`;
Then replace the div with CardPreview component.
{cards.map((card) => (
<CardPreview key={card.id}>
<h2>{card.name}</h2>
<Button success={card.status === 'success'} >
{card.status}
</Button>
</CardPreview>
))}
See Pseudoselectors & Nesting
Update: Reagarding .attrs
This is a chainable method that attaches some props to a styled
component.
It simply allows you to specify prop values when the component is created versus when it's being used. The className prop looks to be a static "card-preview" so may as well set it once and forget it (in this specific case).

Adding click event to React.Js

I'm learning React.Js. I'm trying to attach an event to write something in the console, however i cant get my function to trigger. Does anyone know how i would attach an onClick event to a react div? I apologise if this is a basic question but ive tried several different methods and none of them are working.
I have tried the two ways of triggering the function shown below but neither is working.
So, Ive realised that the reason that the events were not working was because I was rendering server side. If i render on the client then the event triggers. Does anyone know how to make it trigger if i have initially rendered on the server?
class Individual extends React.Component {
handleClick = () => {
alert("GREAT");
}
render() {
const indDiv = {
margin: '5px',
width: '100px',
height: '120px',
cursor: 'pointer',
border: '5px solid pink',
color: 'blue',
float: 'left'
};
return (
<div>
<div onClick={this.handleClick.bind(this)}>
Alert 1
</div>
<div onClick={() => this.handleClick}>
Alert 2
</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
}
Thank you to everyone that contributed to this. After everything i found that because i had initially created this as a server rendered piece, I had to attach the events after the page had rendered. I was using ReactJS.Net and had to initialize it seperately using hydrate.
Both the ways of calling handler function is incorrect in your code.
In your code handleClick is an arrow function hence manual binding is not required.
If it is not an arrow function then the manual binding should be done always in constructor only. Never do binding anywhere else like you did in render.
When you use onClick={() => this.handleClick} this is wrong. It should be onClick={()=> this.handleClick()}. If no Paranthesis then this is correct onClick={this.handleClick}
So change
<div onClick={this.handleClick.bind(this)}>
Alert 1
</div>
<div onClick={() => this.handleClick}>
Alert 2
</div>
To
<div onClick={()=> this.handleClick()}>
Alert 1
</div>
<div onClick={() => this.handleClick()}>
Alert 2
</div>
The reason you should not do binding anywhere else in the component except constructor because for eg you did binding directly in render so what happens in this case is it creates a new function in webpack bundle file every time the component renders and re renders again hence bundle file grows large. Hence it is recommended to bind it only in constructor
You need to declare the handler method after the render method. Here is a basic implementing of your code in jsfiddle.
https://jsfiddle.net/ufyxwv8p/
class Individual extends React.Component {
render() {
const indDiv = {
margin: '5px',
width: '100px',
height: '120px',
cursor: 'pointer',
border: '5px solid pink',
color: 'blue',
float: 'left'
};
return (
<div>
<div onClick={this.handleClick}>
Click to show in console
</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
handleClick = () => {
console.log('this is:', this);
}
}
ReactDOM.render(<Individual/>,document.getElementById("app"))
here try like this the way you are defining your handleclick function is wrong i have edited your code online on sandbox to make it work. call function the way you are calling on Alert 1 than define function the way I have uploaded an image
Link of codesandbox of your code check that
Check this image of that code if you dont have time to go through whole code
The click handler on Alert 1 is already working. It's not necessary to bind when you use a the () => {} class properties syntax.
Your click handler on Alert 2 isn't working because you've written an inline arrow function which returns another function. You need to call it, like () => this.handleClick().
Here is a working snippet of your code.
class Individual extends React.Component {
handleClick = () => {
alert("GREAT");
};
render() {
const indDiv = {
margin: "5px",
width: "100px",
height: "120px",
cursor: "pointer",
border: "5px solid pink",
color: "blue",
float: "left"
};
return (
<div>
<div onClick={this.handleClick}>Alert 1</div>
<div onClick={() => this.handleClick()}>Alert 2</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
}
ReactDOM.render(<Individual />, document.getElementById("app"));
<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>
<div id="app"></div>
You have to use bind
onClick={this.handleClick.bind(this)}
or use arrow function
onClick={()=>this.handleClick()}
class Individual extends React.Component {
handleClick = () => {
alert("GREAT");
};
render() {
const indDiv = {
margin: "5px",
width: "100px",
height: "120px",
cursor: "pointer",
border: "5px solid pink",
color: "blue",
float: "left"
};
return (
<div>
<div onClick={this.handleClick}>Alert 1</div>
<div onClick={this.handleClick}>Alert 2</div>
<div style={indDiv}>
{this.props.num}. {this.props.name}.
</div>
</div>
);
}
}
ReactDOM.render(<Individual />, document.getElementById("app"));

Categories