Adding click event to React.Js - javascript

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"));

Related

What is the proper way of manipulating scroll of overflowed flexbox in ReactJS

Consider the following structure:
.container {
width: 200px;
height: 100px;
overflow: auto;
overflow-y: hidden;
}
.container p {
width: 300px;
height: 100px;
background-color: yellow;
}
<div class="container">
<p>Sample Text1, Sample Text2, Sample Text3</p>
</div>
<button onclick="handleScrollLeft()">Left</button>
<button onclick="handleScrollRight()">Right</button>
Because I'm working in ReactJS, my real code looks more like this:
export function Slider() {
const handleScrollLeft = () => {
}
const handleScrollRight = () => {
}
return (
<>
<div className="container">
<p>Sample Text1, Sample Text2, Sample Text3</p>
</div>
<button onClick="handleScrollLeft">Left</button>
<button onClick="handleScrollRight">Right</button>
</>
);
}
With those 2 buttons I would like to change the scroll value (move left and right respectively). I'm not sure how to handle this kind of change:
In useEffect? (I don't want to force re-render, just expand the scroll functionality to those 2 buttons)
Create custom hook? (Same concern)
Or should I directly modify that DOM element in the handler functions? (I know this is a big no-no in React)
I'm really confused on which approach is correct, any advise or solution with further explanation on why would be appreciated
You can use the useRef hook and the element.scrollBy method.
const STEP = 40;
export function Slider() {
const scrollable = useRef(null);
const handleScrollLeft = () => {
scrollable.current.scrollBy(-STEP, 0);
}
const handleScrollRight = () => {
scrollable.current.scrollBy(STEP, 0);
}
return (
<>
<div className="container" ref={scrollable}>
<p>Sample Text1, Sample Text2, Sample Text3</p>
</div>
<button onClick="handleScrollLeft">Left</button>
<button onClick="handleScrollRight">Right</button>
</>
);
}
You can also use this sandbox as an example.

How can I get top element behavior on children?

Hello thanks for the help in advance. I explain the behavior I want to achieve in react. Here is the sandbox for a better understanding. The behavior of the code is as follows:
There is a div marked with a 1px border and inside it there is a button and another div where it will render an array. Clicking on the button adds that same button to the array and renders it alongside the first one. Multiple clicks on the first button will generate a column of buttons next to the first button. So far so good.
What I want to achieve is that clicking on any of the buttons in the column generates another column of buttons next to the button we click on. And so on. At this point, I'm stuck. Thank you.
import "./styles.css";
import { useState } from "react";
export default function App() {
const [btnCount, setBtnCount] = useState([]);
const style = {
maxWidth: "100px",
display: "flex",
padding: "10px",
border: "solid 1px"
};
function handleAdd() {
setBtnCount(btnCount.concat(btn));
}
const btn = <button onClick={handleAdd}>Click</button>;
return (
<div>
<div style={style}>
<div style={{ margin: "5px" }}>{btn}</div>
<div>
{btnCount.map((e, index) => {
return <div key={index}>{e}</div>;
})}
</div>
</div>
</div>
);
}

conditional operator in react not working with css

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' : ''}`}

How to bypass React's error handling of colors

Trying to figure out if there is away of bypassing React's error handling for colors.
The first inner DIV serves as a default with an empty background if a user inputs a color that is incorrect, whether a Hex color or a string.
The second inner DIV sits on top of the first, and is meant to display the color of this.props.value.
This works fine to show my emptyBackground value in the first div, and when a correct color is inputed by the user, say orange, the second div will display a background color of orange, overlapping the first.
Now if I were to change orange to orangered, this div will change to orangered.
The part I am trying to get around is when I type orangere, it will still show the original orange color instead of the default background of the second div. It seems that react will not prompt a re-render when an improper color has been entered. Any way to get around this?
export default class ColorRender extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.props.onChange(e.target.value);
}
render() {
const disabled = this.props.disabled || this.props.readonly;
return (
<div
style={{ position: 'relative' }}
>
<input
type="text"
value={this.props.value}
placeholder={this.props.placeholder}
onChange={this.onChange}
style={{
marginBottom: 20,
width: `calc(100% - ${COLOR_BOX_WIDTH}px - ${COLOR_BOX_MARGIN_RIGHT}px - ${COLOR_BOX_MARGIN_LEFT}px)`,
}}
disabled={disabled}
/>
<div
style={{
...contentStyle,
backgroundImage: `url(${emptyBackground})`,
}}
/>
<div
className="color-display"
style={{
...contentStyle,
backgroundColor: this.props.value,
zIndex: 1000,
}}
/>
</div>
);
}
}
This behavior has nothing to do with React. Modern browsers will simply ignore attempts to set color properties to an unsupported value. You can easily try this yourself by opening up the dev console, selecting a DOM element somehow, and setting its color to orange with something like myElement.style.backgroundColor = 'orange'. Then try setting it to an invalid value like 'orangere'. The element will remain orange instead of reverting to an default or inherited value.
Probably the best way to address this would be to manually check that the user input is a valid color. Something like the is-color package will check not only if it's a valid color name, but HEX and RGB values as well. If the user input is valid, have React render it as usual. But if it's invalid, you can catch that and use a default or inherited value instead.
Although, this is a standard DOM element behavior (as noted by #jered), you can override it with react.
Wrap the .color-display div with another div (the .color-display-wrapper), and set the default color on it. Update the .color-display background via a CSS variable. If the value in the variable is invalid, the background color would be transparent, and the wrapper's background would be displayed.
class ColorRender extends React.Component {
state = { color: 'orange' };
onChange = (e) => this.setState({ color: e.target.value });
render() {
const {color} = this.state;
return (
<div>
<input type="text" onChange={this.onChange} />
<div className="color-display-wrapper">
<div
className="color-display"
style={{ '--color': color }}
/>
</div>
</div>
);
}
}
ReactDOM.render(
<ColorRender />,
demo
);
:root {
--color: transparent;
}
.color-display-wrapper {
width: 200px;
height: 200px;
background: url(https://picsum.photos/200/200);
}
.color-display {
position: relative;
background: var(--color);
height: 100%;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="demo"></div>

Change the background image dynamically

I would like to modify the image in the background with the help of a comment.
The images come from the tmdb API.
So I think you have to create a background image component and pass it on to the URL.
I know that CSS has the background-image property, but it works for static images ...
What is the best method, I would like to make this component reusable.
Here is how you would have to do it.
Create your <div> and its style with a default background-image
Create 3 <button> to triggers your function changeImage() and provide a parameter
Change the style.backgroundImage with JavaScript such as below:
function changeImage(category){
document.getElementById('div-bg').style.backgroundImage = 'url("https://source.unsplash.com/320x240/?' + category + '")';
}
#div-bg {
display: block;
width: 320px;
height: 240px;
background-image: url("https://source.unsplash.com/320x240/?sky");
}
<div id="div-bg"></div>
<button onclick="changeImage('nature')">Nature</button>
<button onclick="changeImage('animal')">Animal</button>
<button onclick="changeImage('fire')">Fire</button>
If you have any question, please ask!
By doing this it works, I have my background. But I did not manage to do it with a reusable component
import React from 'react';
const VideoDetail = ({ title, description, background }) => {
const IMAGE_BASE_URL = "https://image.tmdb.org/t/p/w500/";
const backgroundStyle = {
color: 'white',
backgroundRepeat: 'no-repeat',
backgroundAttachment: 'scroll',
backgroundPosition: 'center',
backgroundSize: 'cover',
width: "100%",
height: "400px",
backgroundImage: `url(${IMAGE_BASE_URL}${background})`
};
return(
<div>
<div style={background !== undefined ? backgroundStyle : null }>
<h1>{title}</h1>
<p>{description}</p>
</div>
</div>
)
}
export default VideoDetail;import React from 'react';

Categories