React.js get data from js array - javascript

I have the following code:
import React from 'react';
import ProjectsData from './projects.js';
class SingleProject extends React.Component {
render () {
return (
<div className="info-project-wrapper">
<h2>{this.props.title}</h2>
<span className="show-for-large">{this.props.by}</span>
<ul className="project-links show-for-large">
<li>{this.props.links}</li>
</ul>
<div className="info-project">
<p>VIEW NOW</p>
</div>
</div>
)
}
}
class SingleProjectWrapper extends React.Component {
render () {
var projects = [];
this.props.projects.forEach(function(project, i){
projects.push(<SingleProject title={project.title}
by={project.by}
links={projects.links}
key={i} />);
});
return (
<div className="single-project project-4">
{projects}
</div>
)
}
}
class Projects extends React.Component {
render () {
return (
<section>
<SingleProjectWrapper projects={ProjectsData} />
</section>
);
}
}
export default Projects;
and "projectsData" comes from:
var projects = [
{
title: 'title1',
by: 'dfs',
links: ['link-1', 'link-2', 'link-3']
},
{
title: 'title2',
by: 'sdfsd',
links: ['link-1', 'link-2', 'link-3']
},
{
title: 'title3',
by: 'sfsf',
links: ['link-1', 'link-2', 'link-3']
},
{
title: 'title4',
by: 'sdffd',
links: ['link-1', 'link-2', 'link-3']
}
];
export default projects;
most of the data gets displayed correctly apart from <li>{this.props.links}</li>. I only get an empty <li></li> as opposed to "link-1, link-2 and link-3" for each.

You'll need to iterate over the array of links, React doesn't do anything fancy with arrays.
So instead of;
<ul className="project-links show-for-large">
<li>{this.props.links}</li>
</ul>
You'll need to do;
<ul className="project-links show-for-large">
{this.props.links.map(i => <li>i</li>)}
</ul>

Related

Need to Trigger individual Element in an array of elements written through map function reactjs

class Services extends Component {
constructor(props) {
super(props);
this.state = {showoffer: false};
}
showOffers=( )=>{
this.setState({showoffer: !this.state.showoffer});
}
render() {
return (
<div className="OSServicesContainer">
<img className="OSlogomark" src={logomark} alt="logo mark" />
<article className="OssHeadingText">OOM INTERIORS OFFERS</article>
{offersdata.map((offers,index)=>{
return ( <div key={index} className="OssoffersContainermain">
<div className="OssoffersContainer">
<div className="OssofferHeadingmain">
<article className="OssofferHeading">{offers.heading}</article>
</div>
<article className="OssofferText">{offers.subheading}</article>
<div className="OssofferViewbtnmain">
<article key={index} className="OssofferViewbtn" onClick={this.showOffers}>{this.state.showoffer?"View Less":"View More"}</article>
</div>
</div>
{!this.state.showoffer?
null:
<div className="OssOfferSubCompmain">
{offers.offersub.map((offer,key) =>{
return <OssOfferSubComp ofrtext={offer.text} ofrsubtext={offer.subtext} />
})}
</div>}
</div>
)
})}
</div>);
}
}
export default Services;
Above is my code
i want to call showoffer function and update only that element clicked
please what shall i do it is triggering all elements
how to trigger single element??
You can try something like this:
`class Services extends Component {
constructor(props) {
super(props);
this.state = {showoffer: 0};
}
showOffers = ( offerIndex ) => {
this.setState({showoffer: offerIndex});
}
hideOffers = () => {
this.setState({showoffer: 0});
}
render() => {
...
<div className="OssofferViewbtnmain">
<article key={index} onClick={ () => this.showOffers(index) }>
{this.state.showoffer?"View Less":"View More"}
</article>
</div>
...
{
this.state.showOffer && this.state.showOffer === index
? // then show it
: ''
}
}`
Hey if you wish to have multiple items open at the same time you can do something like this where you mutate the mapped item to track show hide state. I have added a visible property to the list item that keeps track if the item is open or closed:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends Component {
state = {
items: [
{ header: "Test 1", extra: "Some extra content A" },
{ header: "Test 2", extra: "Some extra content B" },
{ header: "Test 3", extra: "Some extra content C" }
]
};
onItemClick(index) {
const selected = this.state.items[index];
this.setState({
items: [
...this.state.items.slice(0, index),
{ ...selected, visible: !selected.visible },
...this.state.items.slice(index + 1)
]
});
}
render() {
return (
<div>
<ul>
{this.state.items.map((item, index) => {
return (
<li
key={index}
style={{ cursor: "pointer" }}
onClick={() => this.onItemClick(index)}
>
<h3>{item.header}</h3>
{item.visible ? <div>{item.extra}</div> : null}
</li>
);
})}
</ul>
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/busy-germain-hdmrn

What do I need to change in toggle function to show 1 element at a time rather than show all elements?

I'm building a dog breed info application and when I click on the breed name I want to show the info for that breed only. Currently, the toggle function does show the dog breed info when the breed name is clicked but it shows the info for all breeds rather than just the breed clicked.
I think the problem is that I'm not calling the object id correctly but I can't figure out where the id needs to be called. What am I missing? Thanks!
class Dog extends React.Component {
constructor(props) {
super(props);
this.state = {
dogInfo: [
{
id: 1,
key: 'dogBreed',
breedName: 'Tibetan Mastiff',
class: 'Working',
colors: ['Black', 'Black & Tan', 'Blue Gray', 'Blue Gray & Tan', 'Brown', 'Brown & Tan', 'Red Gold', 'Red Gold Sable'],
image: tibetanMastiff,
alt: 'Black and Tan Tibetan Mastiff'
},
{
id: 2,
key: 'dogBreed',
breedName: 'Great Dane',
class: 'Working',
colors: ['Black', 'Black & White', 'Blue', 'Brindle', 'Fawn', 'Harlequin', 'Mantle', 'Merle', 'White'],
image: greatDane,
alt: 'Merle Great Dane'
},
{
id: 3,
key: 'dogBreed',
breedName: 'Cavalier King Charles Spaniel',
class: 'Toy',
colors: ['Blenheim', 'Black & Tan', 'Tri-Color', 'Ruby'],
image: cavalier,
alt: 'Tri-Color Cavalier King Charles Spaniel'
},
{
id: 4,
key: 'dogBreed',
breedName: 'Italian Greyhound',
class: 'Toy',
colors: ['Black', 'Blue', 'Blue Fawn', 'Cream', 'Fawn', 'Red', 'Red Fawn', 'Sable', 'Seal'],
image: italianGrayhound,
alt: 'Fawn Italian Grayhound'
}
]
}
}
toggleSelected(id, key){
let temp = this.state[key]
temp[id].selected = !temp[id].selected
this.setState({
[key]: temp
})
}
render() {
return (
<div className="App">
<div className='wrapper'>
<DogList
title='Choose Dog Breed'
breedInfo={this.state.dogInfo}
toggleItem={this.toggleSelected}
/>
</div>
</div>
);
}
}
export default Dog;
class DogList extends React.Component {
constructor(props) {
super(props);
this.state = {
listOpen: false,
headerTitle: this.props.title
}
}
toggleList(){
this.setState(prevState => ({
listOpen: !prevState.listOpen
}))
}
render(){
const{breedInfo} = this.props
const{listOpen, headerTitle} = this.state
return(
<div>
<div >{headerTitle}</div>
{<ul onClick={() => this.toggleList()}>
{breedInfo.map((dog) => (
<li key={dog.id} >{dog.breedName}
{listOpen && <ul onClick={() => this.toggleList()}>
<img src={dog.image}/>
<li key={dog.id} >{dog.colors.map((color) => (
<ul>
<li>{color}</li>
</ul>
))}</li>
</ul>}
</li>
))}
</ul>}
</div>
)
}
}
export default DogList;
Hello smallDisgruntledDog, great name by the way. Taking a look at your code, there are a variety of ways to accomplish what you're looking for. As currently constructed, it looks like you are trying to make use of your toggleList()function to display one dog-breed at a time. However, the listOpen value is shared across all of your dogs, so it ends up opening all lists. There is no unique value being passed to determine which dog was selected.
I have 2 ways for you to solve this.
Option 1) Add an extra state value in your DogList component called selectedDog. Update your toggleList function to take in a dog breed value, which we will use to update the selectedDog state. Now in order to display a dog list, both listOpen has to be true and the selectedDog must match dog.breedName:
import React from "react";
class DogList extends React.Component {
constructor(props) {
super(props);
this.state = {
listOpen: false,
headerTitle: this.props.title,
selectedDog: null
};
}
toggleList(dogBreed) {
this.setState(prevState => ({
listOpen: !prevState.listOpen,
selectedDog: dogBreed
}));
}
render() {
const { breedInfo } = this.props;
const { listOpen, headerTitle, selectedDog } = this.state;
return (
<div>
<div>{headerTitle}</div>
{
<ul>
{breedInfo.map(dog => (
<li key={dog.id} onClick={() => this.toggleList(dog.breedName)}>
{dog.breedName}
{listOpen && selectedDog === dog.breedName && (
<ul>
<img src={dog.image} />
<li key={dog.id}>
{dog.colors.map(color => (
<ul>
<li>{color}</li>
</ul>
))}
</li>
</ul>
)}
</li>
))}
</ul>
}
</div>
);
}
}
export default DogList;
Option 2) Separate each Dog into a different component. I'm going to display this using a component called DogBreed. There are many benefits to doing this including writing cleaner code, giving each dog their own state and giving us more control over each dog.
DogBreed component:
import React from "react";
class DogBreed extends React.Component {
state = {
show: false
};
handleClick = () => {
this.setState(prevState => {
return {
show: !prevState.show
};
});
};
render() {
const { show } = this.state;
return (
<li onClick={this.handleClick}>
{this.props.breedName}
{show ? (
<ul>
<img src={this.props.image} />
<li>
{this.props.colors.map(color => (
<ul>
<li>{color}</li>
</ul>
))}
</li>
</ul>
) : null}
</li>
);
}
}
export default DogBreed;
Updated DogList component:
import React from "react";
import DogBreed from "./DogBreed";
class DogList extends React.Component {
constructor(props) {
super(props);
this.state = {
headerTitle: this.props.title
};
}
toggleList() {
this.setState(prevState => ({
listOpen: !prevState.listOpen
}));
}
render() {
const { breedInfo } = this.props;
const { headerTitle } = this.state;
return (
<div>
<div>{headerTitle}</div>
{
<ul>
{breedInfo.map(dog => (
<DogBreed
breedName={dog.breedName}
colors={dog.colors}
image={dog.image}
/>
))}
</ul>
}
</div>
);
}
}
export default DogList;
Let me know if you have any questions. For reference, here are the codesandboxes for both options:
Option 1: https://codesandbox.io/s/1x82qq82j
Option 2: https://codesandbox.io/s/v3062w69v0

ReactJS: What does “this.props.addDog(this.state.newDog);” mean in this code?

I'm studying a React app made up by one main component: App.js (the main one) and three other external components: Dog.js, DogItem.js, AddDog.js The App contain a set of items (Dogs): Dog.js, made up of single dog elements, DogItem.js, and a form: AddDog.js to add a new item: dog.
In the AddDog.js file, the only line I don't realize is: this.props.addDog(this.state.newDog); I have highlighted it below.
I'd like to underline that addDog in this.props.addDog(this.state.newDog); is different from the name of the component AddDog.
Here's AddDog.js
import React, { Component } from 'react';
class AddDog extends Component {
constructor() {
super();
this.state = {
newDog:{}
}
}
static defaultProps = {
categories: ['Web Design', 'Web Development', 'Mobile Development']
}
handleSubmit(e) {
if(this.refs.name.value === '') {
alert('Title is required');
} else if (this.refs.image.value === '') {
alert('Image link is required');
} else if (this.refs.breed.value === '') {
alert('Breed is required');
} else {
this.setState({newDog:{
name: this.refs.name.value,
breed: this.refs.breed.value,
image: this.refs.image.value
}}, function() {
this.props.addDog(this.state.newDog); // <<<<<<<<<<<<<<<<<
});
}
e.preventDefault();
}
render() {
return (
<div>
<h3 id="addDog">Add Dog</h3>
<form onSubmit={this.handleSubmit.bind(this)}>
<div>
<label>Name</label><br />
<input id="dogName" type="text" ref="name" />
</div>
<div>
<label>Image</label><br />
<input id="imageURL" type="text" ref="image" />
</div>
<div>
<label>Breed</label><br />
<input id="dogBreed" type="text" ref="breed" />
</div>
<br />
<input id="submitButton" type="submit" value="Submit" />
<br />
</form>
</div>
);
}
}
export default AddDog;
Here's the App.js
import React, { Component } from 'react';
import Dogs from './components/Dogs';
import DogItem from './components/DogItem';
import AddDog from './components/AddDog';
import './App.css';
class App extends Component {
constructor() {
super();
this.state = {
dogs: []
};
}
getDogs() {
var defaultDogs = {dogs: [
{
name: 'Princess',
breed: 'Corgi',
image: 'https://s-media-cache-ak0.pinimg.com/originals/51/ae/30/51ae30b78696b33a64661fa3ac205b3b.jpg'
},
{
name: 'Riley',
breed: 'Husky',
image: 'http://portland.ohsohandy.com/images/uploads/93796/m/nice-and-sweet-siberian-husky-puppies-for-free-adoption.jpg'
},
]};
this.setState(defaultDogs);
}
componentWillMount() { // this soon display the two dogs before the render
this.getDogs();
}
handleAddDog(dog) {
let dogs = this.state.dogs;
dogs.push(dog);
this.setState({dogs:dogs});
}
handleDeleteDog(name) {
let dogs = this.state.dogs;
let index = dogs.findIndex(x => x.name === name); // function (x) {return x.name === name} is like x => x.name === name
dogs.splice(index, 1);
this.setState({dogs:dogs});
}
render() {
return (
<div className="App">
<Dogs dogs={this.state.dogs} onDelete={this.handleDeleteDog.bind(this)} />
<AddDog addDog={this.handleAddDog.bind(this)} />
<hr />
</div>
);
}
}
export default App;
Here's Dog.js
import React, { Component } from 'react';
import DogItem from './DogItem';
class Dogs extends Component {
deleteDog(name) {
this.props.onDelete(name);
}
render() {
let dogItem;
if (this.props.dogs) {
dogItem = this.props.dogs.map(dog => {
return (
<DogItem onDelete={this.deleteDog.bind(this)} key={dog.name} dog={dog} />
);
});
}
return (
<div className="Dogs">
<h1>Good Dogs</h1>
{dogItem}
</div>
);
}
}
export default Dogs;
Here's DogItem.js
import React, { Component } from 'react';
class DogItem extends Component {
deleteDog(name) {
this.props.onDelete(name);
}
render() {
return (
<ul className="Dog">
<img src={this.props.dog.image} href={this.props.dog.image} role="presentation" width="100" height="100"></img>
<br></br>
<strong>{this.props.dog.name}</strong>: {this.props.dog.breed} <a href="#" onClick={this.deleteDog.bind(this, this.props.dog.name)}>X</a>
<br></br>
</ul>
);
}
}
export default DogItem;
It's a callback function from the parent component. (In this case App.js)
It's used to add the new dog into the dogs array in the App's state.
So when you the function this.props.addDog(this.state.newDog) is called, it's calling the function that has been passed in as a prop by the parent component
(<AddDog addDog={this.handleAddDog.bind(this)} /> in App.js)
Which means when you call this.props.addDog(this.state.newDog),
this.handleAddDog() gets called in the App.js component with the new Dog Object as the argument (this.handleAddDog(this.state.newDog) with "this.state" refering to the state of the AddDog Component)
I hope that was detailed and clear enough ;)

Loop through simple array of objects in React

I am not using JSX. Is this a problem? Is this considered bad practice?
var links = [
{ endpoint: '/america' },
{ endpoint: '/canada' },
{ endpoint: '/norway' },
{ endpoint: '/bahamas' }
];
class Navigation extends React.Component {
render() {
return (
<div className="navigation">
<ul>
const listItems = links.map((link) =>
<li key={link.endpoint}>{link.endpoint}</li>
);
</ul>
</div>
);
}
Based on the basic list component section of the react docs, it seems like I should be able to print the contents of an array, the way I'm doing it inside my <ul></ul>
https://facebook.github.io/react/docs/lists-and-keys.html#basic-list-component
Is the problem that I am using an array of objects? The docs are using a simple array. I'd appreciate a push into the right direction.
The issue is that your syntax is invalid, you should have something like this :
var links = [
{ endpoint: '/america' },
{ endpoint: '/canada' },
{ endpoint: '/norway' },
{ endpoint: '/bahamas' }
];
class Navigation extends React.Component {
render() {
const listItems = links.map((link) =>
<li key={link.endpoint}>{link.endpoint}</li>
);
return (
<div className="navigation">
<ul>
{listItems}
</ul>
</div>
);
}
You should be able to do something like this:
class Navigation extends React.Component {
render() {
return (
<div className="navigation">
<ul>
{
links.map(link =>
<li key={link.endpoint}>{link.endpoint}</li>
)
}
</ul>
</div>
);
}

Cannot read property left of undefined. Jquery Error [duplicate]

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'});
});
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.
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.
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>
)
}
}
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'));`
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>
)}
)}
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>
);
}
import React from 'react';
class MyComponent extends React.Component {
getComponent(event) {
event.target.style.backgroundColor = '#ccc';
// or you can write
//arguments[0].target.style.backgroundColor = '#ccc';
}
render() {
return(
<div>
<ul>
<li onClick={this.getComponent.bind(this)}>Component 1</li>
</ul>
</div>
);
}
}
export { MyComponent }; // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;
class FrontendSkillList extends React.Component {
constructor() {
super();
this.state = { selectedSkill: {} };
}
render() {
return (
<ul>
{this.props.skills.map((skill, i) => (
<li
className={
this.state.selectedSkill.id === skill.id ? "selected" : ""
}
onClick={this.selectSkill.bind(this, skill)}
style={{ cursor: "pointer" }}
key={skill.id}
>
{skill.name}
</li>
))}
</ul>
);
}
selectSkill(selected) {
if (selected.id !== this.state.selectedSkill.id) {
this.setState({ selectedSkill: selected });
} else {
this.setState({ selectedSkill: {} });
}
}
}
const data = [
{ id: "1", name: "HTML5" },
{ id: "2", name: "CSS3" },
{ id: "3", name: "ES6 & ES7" }
];
const element = (
<div>
<h1>Frontend Skill List</h1>
<FrontendSkillList skills={data} />
</div>
);
ReactDOM.render(element, document.getElementById("root"));
.selected {
background-color: rgba(217, 83, 79, 0.8);
}
<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="root"></div>
#user544079 Hope this demo can help :) I recommend changing background color by toggling classname.
import React from 'react';
class MyComponent extends React.Component {
getComponent(event) {
event.target.style.backgroundColor = '#ccc';
// or you can write
//arguments[0].target.style.backgroundColor = '#ccc';
}
render() {
return(
<div>
<ul>
<li onClick={this.getComponent.bind(this)}>Component 1</li>
</ul>
</div>
);
}
}
export { MyComponent }; // use this to be possible in future imports with {} like: import {MyComponent} from './MyComponent'
export default MyComponent;
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()
{
return(
<ul>
{this.state.items.map((val, ind) => {
let item = <li key={ind}>{val}</li>;
let props = {
onClick: () => this.Click(item, ind),
key : ind,
ind
}
let clone = React.cloneElement(item, props, [val]);
return clone;
})}
</ul>
)
}
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.

Categories