Changing style of a button on click - reactjs

Is it possible to change background-color of my button onClick function?
ex. click background-color: black, another click background-color: white
I've tried something like this.style, no result.
I've managed to get overlay working and insert needed data inside of it.
But didn't managed to find any post that could help me.
I am using react-bootstrap.
This is my code.
const metaDataOverlay = (
<div>
<style type="text/css">{`
.btn-overlay {
background-color: white;
margin-right: -15px;
margin-left: -15px;
padding-bottom: -20px;
padding: 0;
}
`}</style>
<ButtonToolbar>
<ButtonGroup>
<OverlayTrigger trigger={['hover', 'focus']} placement="left" overlay={popoverHoverFocus}>
<Button bsStyle="overlay" onClick={ clicked } onKeyPress={ keypress }>
<div className={bemBlocks.item().mix(bemBlocks.container("item"))} data-qa="hit">
<a href={url} onClick={(e)=>{e.preventDefault(); console.log("123")}}>
<div>
<img data-qa="poster" className={bemBlocks.item("poster")} src={result._source.poster} width="240" height="240"/>
</div>
</a>
</div>
</Button>
</OverlayTrigger>
</ButtonGroup>
</ButtonToolbar>
</div>
)

You can try to use state to store the color. Maybe this would give you the idea how to solve the problem :
class Test extends React.Component {
constructor(){
super();
this.state = {
black: true
}
}
changeColor(){
this.setState({black: !this.state.black})
}
render(){
let btn_class = this.state.black ? "blackButton" : "whiteButton";
return (
<button className={btn_class} onClick={this.changeColor.bind(this)}>
Button
</button>
)
}
}
React.render(<Test />, document.getElementById('container'));
Here is a fiddle.

You also have access to event and current target of the event
handleClick = (event) => {
// accessible
event.target.style
event.target.classList //to change style via css
}

Here is another solution
changeStyles = () => {
let element = document.getElementById('button')
ReactDOM.findDOMNode(element).style.backgroundColor = this.state.isClicked?'black' : 'white'
}
In this way you can change only needed style property preventing duplicates in CSS.

This is how you can access
handleClick=(e)=>{
console.log("this is working fine");
e.preventDefault();
e.target.style.color = 'black'
console.log(e.target);
}
If you want more dynamically you can initialize state with some default value of style afterwords use setState function to update your state

Add this to your Tooltip
<Tooltip cursor={{ fill: 'transparent' }} />

Here is another solution :
import React, { Component } from 'react';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
BackgroundColor: "BLACK"};
};
render(){
return (
<div className='app'>
<button className={this.state.BackgroundColor === "BLACK" ? "Black" : "nothing"}
onClick={() => {this.setState({BackgroundColor: "WHITE"})}}>CHANGE TO BLACK</button>
<button className={this.state.BackgroundColor === "WHITE" ? "White" : "nothing"}
onClick={() => {this.setState({BackgroundColor: "BLACK"})}}>CHANGE TO WHITE</button>
</div>
);
}
}
export default App;
This code will help you to hide the ex black button and change with new button with white background. This function will also work for the new white button. If maybe you just want to change background-color of button without repeat situation you can also try to change conditional state in render
render(){
return (
<div className='app'>
<button className={this.state.BackgroundColor === "BLACK" ? "Black" : "White"}
onClick={() => {this.setState({BackgroundColor: "WHITE"})}}>CHANGE TO BLACK</button>
</div>
);
}
}
Here is the CSS :
*{
margin: 0;
padding: 0;
}
.app{
display: flex;
justify-content: center;
align-items: center;
}
.Black{
background-color: black;
color: white;
}
.White{
background-color: white;
color: black;
}
.nothing{
display: none;
}

Related

ReactJS clicking button

I am hoping that you can help me with this task, I just want to create a Like button, the initial counter for the button is 100, if the button is clicked it will add 1 and it will highlight (you can use the classname tool) and if the user undo their like it will decrease by one and it will not highlight
import cx from 'classnames';
import { Component } from 'react';
export default class LikeButton extends Component {
state = {
active: false,
count: 100
}
formatCount() {
const {count} = this.state.count
return count === 100 ? 100 : 101
}
render() {
return (
<>
<div>
<button className={this.state.active === false ? 'like' : 'like-button'}>Like | {this.formatCount()}</button>
</div>
<style>{`
.like-button {
font-size: 1rem;
padding: 5px 10px;
color: #585858;
}
.liked {
font-weight: bold;
color: #1565c0;
}
`}</style>
</>
);
}
}
Here's how to do it using functional components in React (which I'd strongly recommend):
import "./like.css"
export default function Like(){
const [count, setCount] = useState(100);
const [active, setActive] = useState(false);
function handleClick(){
if(active) {
// handle unliking
setActive(false);
setCount(oldCount => oldCount - 1);
} else {
// handle liking
setActive(true);
setCount(oldCount => oldCount + 1);
}
}
return(
<div>
<button
className={active ? 'liked' : 'unliked'}
onClick={handleClick}
>
Like | {count}
</button>
</div>
)
}
and like.css contents:
.unliked {
font-size: 1rem;
padding: 5px 10px;
color: #585858;
}
.liked {
font-weight: bold;
color: #1565c0;
}
You can rework this to the class-based approach pretty easily (though I'd recommend using functional components, they're really cool). Basically, you keep track of the count and whether or not they've already pressed the like button, and conditionally handle onClick based on the current state.

How can i hover in React using useState

I wanna toggle a class when hovering on a Container by changing the opacity from 0 to 1, I've used onmouseEnter and onMouseLeave Event to toggle the class, but when I console hover state I see that is changing from true to false when I hover but the class "Show" is not changing.
What do you think ?
<--Components-->
import React,{useState} from 'react';
import './MyWork.css';
import {Visibility, GitHub } from "#material-ui/icons";
const SingleProject = ({src, title}) => {
const [hover, isHover] = useState(false);
const showIcons = isHover ? "Show" : "";
return (
<div className="card-container" onMouseEnter={()=> isHover(true)} onMouseLeave={()=> isHover(false)}>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${showIcons}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;
<--- Css--->
.card-container {
height: 314px;
width: 500px;
cursor: pointer;
position : relative;
}
.Info {
position: absolute;
height: 100%;
width: 100%;
top:0;
left:0;
display:flex;
justify-content:center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
opacity: 0;
}
.Info.Show {
opacity: 1;
}
When assigning the value to showIcons, you need to use hover instead of isHover which is the setter function for that state.
Additionally, I recommend naming the setter function setHover to avoid confusion and be more semantic. You can also add conditional Show class like this, which is more concise:
iconst SingleProject = ({src, title}) => {
const [hover, setHover] = useState(false);
return (
<div
className="card-container"
onMouseEnter={()=> setHover(true)}
onMouseLeave={()=> setHover(false)}
>
<img src={src} alt={title}/>
<h1 id="card-title">{title}</h1>
<div className={`Info ${hover ? "Show" : ""}`}>
<div className="Icon">
<GitHub/>
</div>
<div className="Icon">
<Visibility/>
</div>
</div>
</div>
)
}
export default SingleProject;
You are using the setter instead of the state itself on your condition. Change isHover with hover like below:
const showIcons = hover ? "Show" : "";

Overlay is blocking input to xlsx spreadsheet how to fix that in my case

I created a codesandbox to illustrate this.
Basically what happens is the XLSX spreadsheet cells can't be clicked on because the overlay transparent box is blocking this. I know why this happens and it can be fixed by setting style pointer-events: none; But then the overlay stops working because it slides out when mouse moves.
The overlay with green buttons slides in and out and the "Box" that catches the mouse move for the overlay is blocking the clicks to go through to the spreadsheet under.
How can I fix so I can edit all cells in the spreadsheet and still have the overlay working? IS there a way to make an overlay like this that let click through and also react to mouse events?
Unfortunately it seems impossible to achieved that having the Overlay as a sibling of the element you're overlaying, but it works if you are allowed to change the structure putting the XLSX component as child of the overlay
Overlay.js
class Overlay extends Component {
constructor(props) {
super(props);
this.state = {
hoverIndex: null
};
}
handleMouseEnter = (e) => {
if (e.currentTarget.id) {
this.setState({ hoverIndex: e.currentTarget.id });
}
};
handleMouseLeave = (e) => {
this.setState({ hoverIndex: null });
};
render() {
const { fileData, children } = this.props;
const { hoverIndex } = this.state;
return (
<div
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
className={`box-container`}
id={fileData}
key={fileData}
>
<div
onMouseLeave={this.handleMouseLeave}
className={`box-content ${hoverIndex === fileData ? "hovered" : ""}`}
>
<div className="text-group">SpreadSheet File</div>
<div className="btn-group">
<button className="btn btn-secondary" type="button">
Open File
</button>
<button className="btn btn-secondary" type="button">
Edit Description
</button>
<button className="btn btn-secondary" type="button">
Download
</button>
<button className="btn btn-secondary" type="button">
Push me for fun
</button>
</div>
</div>
{children}
</div>
);
}
}
overlay-xlsx-renderer.scss
.box-container {
width: 100%;
height: 100%;
margin: 0% auto;
overflow: hidden;
position: relative;
}
.box-content {
width: 60%;
height: 100%;
background: #1d1d1e;
position: absolute;
left: -60%;
transition: left 0.6s;
color: white;
overflow: auto;
z-index: 10;
}
ItemRendered.js
...
case "xlsx": {
return (
<div className="outer">
<Overlay fileData={fileData}>
<div className="pg-viewer-wrapper">
<div className="pg-viewer" id="pg-viewer">
<XlsxViewer
responseType="arraybuffer"
filePath={filePath}
width={0}
height={0}
/>
</div>
</div>
</Overlay>
</div>
);
}
...
you can check it working in this sandbox fork

How to Prevent Parent Component State from Resetting to Original after Closing the Child Component

I have a search form with a lot of search components and a List container component which contains Item component to display the search results. When I click a selected Item, it pops up a Detail component. Right now, everything works fine except when clicking Close button inside the Detail component, the form gets reset and list of items also disappears. The Close button should just close the Detail component so I can select a different item in the list to view. What is the problem in my code? Thanks.
App.js
class App extends Component {
state={ showPopup: false,
selectedItem:'',
Items:[]};
togglePopup=()=> {
this.setState({
showPopup: !this.state.showPopup
});
}
onItemseSelect=(item)=>{
this.setState({selectedItem:item});
};
render(){
const Items=['aa','bb','cc'];
return(
<List
Items={this.state.Items}
onItemSelect={this.onItemSelect}
onClick={this.togglePopup}
/>
{this.state.showPopup ?
<Detail
item={this.state.selectedItem}
closePopup={this.togglePopup.bind(this)}
/>
: null
}
);
}
}
List.js
import React from 'react';
import Item from './Item';
const List=({Items,onItemSelect})=>{
const renderedList= Items.map(item=>{
return (
<Item key={item.ID} item={item} onItemSelect={onItemSelect} />
);
})
return <div>
{renderedList}</div>
}
export default List;
Item.js
import React from 'react';
const Item=({item, onItemSelect})=>{
return <div onClick={()=>onItemSelect(item)} >
<div class="content">
<div class="header">
{/*display contents*/}
View More
</div>
</div>
};
export default Item;
Detail.js
import React from 'react';
const Detail=({item,closePopup})=>{
if (!item){
return <div>loading</div>
}
return (
<div className='popup'>
<div className='popup_inner'>
<p>
{/*contents here*/}
</p>
<button onClick={()=>closePopup}>close me</button>
</div>
</div>);
};
export default Detail;
css code:
.popup {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
background-color: rgba(0,0,0, 0.5);
}
.popup_inner {
position: absolute;
left: 25%;
right: 25%;
top: 25%;
bottom: 25%;
margin: auto;
background: white;
}
No error message. The form resets to the original state.
I think the problem is here only, I doubt how your list items are rendered first time only.
Items:[]
render(){
const Items=['aa','bb','cc']; //static values which are not in use
return(
<List
Items={this.state.Items} //You are using state which is blank
onItemSelect={this.onItemSelect}
onClick={this.togglePopup}
/>
...
)
}
Complete Running code is like this.

Put inside Textarea button with Jsx (react)

Okey small question from junior to pro about Jsx and react:
I have textarea and i wanna put inside button
renderButton() {
const { mod } = this.state
return (
<button className={classNames({
[styles.button]: mod == 'default',
[styles.fullScreenButton]: mod == 'fullscreen'
})} onClick={this.fullScreen} >
{this.renderIcon()}
</button>
)
}
render() {
const { text, rows } = this.props
const { mod } = this.state
return (
<div>
<textarea rows={rows} value='text'
className={classNames({
[styles.textArea]: mod == 'default',
[styles.fullScreen]: mod == 'fullscreen'
})}>
</textarea>
{this.renderButton()}
</div>
)
}
}
How i can do that?
Just
<textarea> <button> </button> </textarea>
not working
Using position: absolute maybe yes, but have any another way to do that?
As you have discovered, placing an HTML button as a child of a <textarea> will not work. This is not a limitation of React or JSX but of the <textarea> element. If you want the button to be placed inside the <textarea> visually you'll need to use CSS to reposition it. Something like this:
div {
position: relative;
}
textarea {
width: 100%;
height: 300px;
margin: 0;
padding: 0;
}
button {
position: absolute;
bottom: 15px;
right: 10px;
}
<div>
<textarea>
</textarea>
<button>Submit</button>
</div>

Resources