I have
var TestApp = React.createClass({
getComponent: function(){
console.log(this.props);
},
render: function(){
return(
<div>
<ul>
<li onClick={this.getComponent}>Component 1</li>
</ul>
</div>
);
}
});
React.renderComponent(<TestApp />, document.body);
I want to color the background of the clicked list element. How can I do this in React ?
Something like
$('li').on('click', function(){
$(this).css({'background-color': '#ccc'});
});
This question is related to
javascript
jquery
reactjs
class FrontendSkillList extends React.Component {_x000D_
constructor() {_x000D_
super();_x000D_
this.state = { selectedSkill: {} };_x000D_
}_x000D_
render() {_x000D_
return (_x000D_
<ul>_x000D_
{this.props.skills.map((skill, i) => (_x000D_
<li_x000D_
className={_x000D_
this.state.selectedSkill.id === skill.id ? "selected" : ""_x000D_
}_x000D_
onClick={this.selectSkill.bind(this, skill)}_x000D_
style={{ cursor: "pointer" }}_x000D_
key={skill.id}_x000D_
>_x000D_
{skill.name}_x000D_
</li>_x000D_
))}_x000D_
</ul>_x000D_
);_x000D_
}_x000D_
_x000D_
selectSkill(selected) {_x000D_
if (selected.id !== this.state.selectedSkill.id) {_x000D_
this.setState({ selectedSkill: selected });_x000D_
} else {_x000D_
this.setState({ selectedSkill: {} });_x000D_
}_x000D_
}_x000D_
}_x000D_
_x000D_
const data = [_x000D_
{ id: "1", name: "HTML5" },_x000D_
{ id: "2", name: "CSS3" },_x000D_
{ id: "3", name: "ES6 & ES7" }_x000D_
];_x000D_
const element = (_x000D_
<div>_x000D_
<h1>Frontend Skill List</h1>_x000D_
<FrontendSkillList skills={data} />_x000D_
</div>_x000D_
);_x000D_
ReactDOM.render(element, document.getElementById("root"));
_x000D_
.selected {_x000D_
background-color: rgba(217, 83, 79, 0.8);_x000D_
}
_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>_x000D_
_x000D_
<div id="root"></div>
_x000D_
@user544079 Hope this demo can help :) I recommend changing background color by toggling classname.
import React from 'react';_x000D_
_x000D_
class MyComponent extends React.Component {_x000D_
_x000D_
getComponent(event) {_x000D_
event.target.style.backgroundColor = '#ccc';_x000D_
_x000D_
// or you can write_x000D_
//arguments[0].target.style.backgroundColor = '#ccc';_x000D_
}_x000D_
_x000D_
render() {_x000D_
return(_x000D_
<div>_x000D_
<ul>_x000D_
<li onClick={this.getComponent.bind(this)}>Component 1</li>_x000D_
</ul>_x000D_
</div>_x000D_
);_x000D_
}_x000D_
}_x000D_
_x000D_
export { MyComponent }; // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'_x000D_
export default MyComponent;
_x000D_
Two ways I can think of are
var TestApp = React.createClass({
getComponent: function(index) {
$(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
'background-color': '#ccc'
});
},
render: function() {
return (
<div>
<ul>
<li onClick={this.getComponent.bind(this, 1)}>Component 1</li>
<li onClick={this.getComponent.bind(this, 2)}>Component 2</li>
<li onClick={this.getComponent.bind(this, 3)}>Component 3</li>
</ul>
</div>
);
}
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));
This is my personal favorite.
var ListItem = React.createClass({
getInitialState: function() {
return {
isSelected: false
};
},
handleClick: function() {
this.setState({
isSelected: true
})
},
render: function() {
var isSelected = this.state.isSelected;
var style = {
'background-color': ''
};
if (isSelected) {
style = {
'background-color': '#ccc'
};
}
return (
<li onClick={this.handleClick} style={style}>{this.props.content}</li>
);
}
});
var TestApp2 = React.createClass({
getComponent: function(index) {
$(this.getDOMNode()).find('li:nth-child(' + index + ')').css({
'background-color': '#ccc'
});
},
render: function() {
return (
<div>
<ul>
<ListItem content="Component 1" />
<ListItem content="Component 2" />
<ListItem content="Component 3" />
</ul>
</div>
);
}
});
React.renderComponent(<TestApp2 /> , document.getElementById('soln2'));
Here is a DEMO
I hope this helps.
Why not:
onItemClick: function (event) {
event.currentTarget.style.backgroundColor = '#ccc';
},
render: function() {
return (
<div>
<ul>
<li onClick={this.onItemClick}>Component 1</li>
</ul>
</div>
);
}
And if you want to be more React-ive about it, you might want to set the selected item as state of its containing React component, then reference that state to determine the item's color within render
:
onItemClick: function (event) {
this.setState({ selectedItem: event.currentTarget.dataset.id });
//where 'id' = whatever suffix you give the data-* li attribute
},
render: function() {
return (
<div>
<ul>
<li onClick={this.onItemClick} data-id="1" className={this.state.selectedItem == 1 ? "on" : "off"}>Component 1</li>
<li onClick={this.onItemClick} data-id="2" className={this.state.selectedItem == 2 ? "on" : "off"}>Component 2</li>
<li onClick={this.onItemClick} data-id="3" className={this.state.selectedItem == 3 ? "on" : "off"}>Component 3</li>
</ul>
</div>
);
},
You'd want to put those <li>
s into a loop, and you need to make the li.on
and li.off
styles set your background-color
.
Handling events with React elements is very similar to handling events on DOM elements. There are some syntactic differences:
- React events are named using camelCase, rather than lowercase.
- With JSX you pass a function as the event handler, rather than a string.
So as mentioned in React documentation, they quite similar to normal HTML when it comes to Event Handling, but event names in React using camelcase, because they are not really HTML, they are JavaScript, also, you pass the function while we passing function call in a string format for HTML, they are different, but the concepts are pretty similar...
Look at the example below, pay attention to the way event get passed to the function:
function ActionLink() {
function handleClick(e) {
e.preventDefault();
console.log('The link was clicked.');
}
return (
<a href="#" onClick={handleClick}>
Click me
</a>
);
}
If you're using ES6, here's some simple example code:
import React from 'wherever_react_is';
class TestApp extends React.Component {
getComponent(event) {
console.log('li item clicked!');
event.currentTarget.style.backgroundColor = '#ccc';
}
render() {
return(
<div>
<ul>
<li onClick={this.getComponent.bind(this)}>Component 1</li>
</ul>
</div>
);
}
}
export default TestApp;
In ES6 class bodies, functions no longer require the 'function' keyword and they don't need to be separated by commas. You can also use the => syntax as well if you wish.
Here's an example with dynamically created elements:
import React from 'wherever_react_is';
class TestApp extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{name: 'Name 1', id: 123},
{name: 'Name 2', id: 456}
]
}
}
getComponent(event) {
console.log('li item clicked!');
event.currentTarget.style.backgroundColor = '#ccc';
}
render() {
<div>
<ul>
{this.state.data.map(d => {
return(
<li key={d.id} onClick={this.getComponent.bind(this)}>{d.name}</li>
)}
)}
</ul>
</div>
);
}
}
export default TestApp;
Note that each dynamically created element should have a unique reference 'key'.
Furthermore, if you would like to pass the actual data object (rather than the event) into your onClick function, you will need to pass that into your bind. For example:
New onClick function:
getComponent(object) {
console.log(object.name);
}
Passing in the data object:
{this.state.data.map(d => {
return(
<li key={d.id} onClick={this.getComponent.bind(this, d)}>{d.name}</li>
)}
)}
This is a non-standard (but not so uncommon) React pattern that doesn't use JSX, instead putting everything inline. Also, it's Coffeescript.
The 'React-way' to do this would be with the component's own state:
(c = console.log.bind console
)
mock_items: [
{
name: 'item_a'
uid: shortid()
}
{
name: 'item_b'
uid: shortid()
}
{
name: 'item_c'
uid: shortid()
}
]
getInitialState: ->
lighted_item: null
render: ->
div null,
ul null,
for item, idx in @mock_items
uid = item.uid
li
key: uid
onClick: do (idx, uid) =>
(e) =>
# justf to illustrate these are bound in closure by the do lambda,
c idx
c uid
@setState
lighted_item: uid
style:
cursor: 'pointer'
background: do (uid) =>
c @state.lighted_item
c 'and uid', uid
if @state.lighted_item is uid then 'magenta' else 'chartreuse'
# background: 'chartreuse'
item.name
This example works -- I tested it locally. You can check out this example code exactly at my github. Originally the env was only local for my own whiteboard r&d purposes but I posted it to Github for this. It may get written over at some point but you can check out the commit from Sept 8, 2016 to see this.
More generally, if you want to see how this CS/no-JSX pattern for React works, check out some recent work here. It's possible I will have time to fully implement a POC for this app idea, the stack for which includes NodeJS, Primus, Redis, & React.
Use ECMA2015. Arrow functions make "this" a lot more intuitive.
import React from 'react';
class TestApp extends React.Component {
getComponent(e, index) {
$(e.target).css({
'background-color': '#ccc'
});
}
render() {
return (
<div>
<ul>
<li onClick={(e) => this.getComponent(e, 1)}>Component 1</li>
<li onClick={(e) => this.getComponent(e, 2)}>Component 2</li>
<li onClick={(e) => this.getComponent(e, 3)}>Component 3</li>
</ul>
</div>
);
}
});
React.renderComponent(<TestApp /> , document.getElementById('soln1'));`
You can make use of the React.createClone method. Create your element, than create a clone of it. During the clone's creation, you can inject props. Inject an onClick : method prop like this
{ onClick : () => this.changeColor(originalElement, index) }
the changeColor method will set the state with the duplicate, allowing you sto set the color in the process.
render()_x000D_
{_x000D_
return(_x000D_
<ul>_x000D_
_x000D_
{this.state.items.map((val, ind) => {_x000D_
let item = <li key={ind}>{val}</li>;_x000D_
let props = { _x000D_
onClick: () => this.Click(item, ind),_x000D_
key : ind,_x000D_
ind_x000D_
}_x000D_
let clone = React.cloneElement(item, props, [val]);_x000D_
return clone;_x000D_
})}_x000D_
_x000D_
</ul>_x000D_
)_x000D_
}
_x000D_
Here is how you define a react onClick event handler, which was answering the question title... using es6 syntax
import React, { Component } from 'react';
export default class Test extends Component {
handleClick(e) {
e.preventDefault()
console.log(e.target)
}
render() {
return (
<a href='#' onClick={e => this.handleClick(e)}>click me</a>
)
}
}
import React from 'react';_x000D_
_x000D_
class MyComponent extends React.Component {_x000D_
_x000D_
getComponent(event) {_x000D_
event.target.style.backgroundColor = '#ccc';_x000D_
_x000D_
// or you can write_x000D_
//arguments[0].target.style.backgroundColor = '#ccc';_x000D_
}_x000D_
_x000D_
render() {_x000D_
return(_x000D_
<div>_x000D_
<ul>_x000D_
<li onClick={this.getComponent.bind(this)}>Component 1</li>_x000D_
</ul>_x000D_
</div>_x000D_
);_x000D_
}_x000D_
}_x000D_
_x000D_
export { MyComponent }; // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'_x000D_
export default MyComponent;
_x000D_
Source: Stackoverflow.com