ReactJS - Target random element - javascript

I have some problems understanding how you interact with element in React after rendering. I currently got this fiddle: https://jsfiddle.net/y7dh3vh5/
var items = ["Afghanistan","Albania","Algeria","Andorra","Angola"....
var RepeatModule = React.createClass({
getDefaultProps: function() {
return { items: [] }
},
render: function() {
var listItems = this.props.items.map(function(item, i) {
return (
<div className="item" key={i}>
<p>{item}</p>
</div>
);
});
return (
<div>
{listItems}
</div>
);
}});ReactDOM.render(<RepeatModule items={items} />, document.getElementById('itemList'));
And I'm looking for a way to highlight a random country when I press the "Highlight random country"-button. Is there an easy way to implement this?
Thanks in advance.

Add state to save highlightedIndex:
getInitialState () {
return {
highlightedIndex: -1
}
},
Add method for button
setNewTarget: function() {
var l = this.props.items.length - 1;
this.setState({
highlightedIndex: this.randomInteger(0, l)
})
},
Put button into return render
return (
<div>
<button onClick={this.setNewTarget}>
Highlight random country
</button>
{listItems}
</div>
);
Live example: https://jsfiddle.net/ufmagg4o/

Just keep your index element in state and compare it in map method. I prefere es6 so i hope you will understand
class Example extends React.Component {
constructor(){
this.state = {
items: ['hello', 'world', 'random', 'highlight'],
index: null
}
this.click = this.click.bind(this);
}
click(){
const items = this.state.items;
const index = Math.floor(Math.random()*items.length);
this.setState({index: index})
}
render(){
const list = this.state.items.map((item,index)=>{
return <p key={index} className={this.state.index === index ? 'item': null}>
{item}
</p>
})
return <div>
<button onClick={this.click}>Click me</button>
{list}
</div>
}
}
React.render(<Example />, document.getElementById('container'));
fiddle example
Thanks!

The key is to keep that button inside React. Don't try to manipulate React components from outside React.
<script src="https://facebook.github.io/react/js/jsfiddle-integration-babel.js"></script>
<div id="itemList">
</div>
.highlighted {
color: white;
background-color: tomato;
}
var items = [
"Afghanistan",
"Albania",
"Algeria",
"Andorra",
"Angola"
]; // etc...
var RepeatModule = React.createClass({
getDefaultProps: function() {
return { items: [] }
},
getInitialState() {
return {highlighted: null};
},
onClickButton() {
this.setState({
highlighted: (Math.random() * this.props.items.length)|0
});
},
render: function() {
var _this = this;
var listItems = this.props.items.map(function(item, i) {
return (
<div className="item" key={i}>
<p className={i == _this.state.highlighted ? 'highlighted' : null}>
{item}
</p>
</div>
);
});
return (
<div>
<button onClick={this.onClickButton}>
Highlight random country
</button>
<div>
{listItems}
</div>
</div>
);
}
});
ReactDOM.render(<RepeatModule items={items} />, document.getElementById('itemList'));
jsfiddle
ES2015 version:
const items = [
"Afghanistan",
"Albania",
"Algeria",
"Andorra",
"Angola"
]; // etc...
class RepeatModule extends React.Component {
static propTypes = {items: React.PropTypes.arrayOf(React.PropTypes.string)};
static defaultProps = {items: []};
state = { highlighted: null };
onClickButton = () => {
this.setState({
highlighted: (Math.random() * this.props.items.length)|0
});
};
render() {
const listItems = this.props.items.map((item, i) => (
<div className="item" key={i}>
<p className={i == this.state.highlighted ? 'highlighted' : null}>
{item}
</p>
</div>
));
return (
<div>
<button onClick={this.onClickButton}>
Highlight random country
</button>
<div>
{listItems}
</div>
</div>
);
}
});
ReactDOM.render(<RepeatModule items={items} />, document.getElementById('itemList'));

Related

Parent state passed as props not updated when rendered in .map function

In the TableAndInfo Component, each row's parent element is rendered by the renderEls function and the content is returned by the renderSection function. This passes in the content in the sections property as a parameter, as well as the class of the parent container. Passing the props value of date, time, and current in the sections array results in a successful initial render, but they do not continue updating when the state changes. I have inspected the code with the React Developer Tools and I see that the state is being updated by the functions defined in the App function and other components. How do I ensure that the grandchildren elements are re-rendered when the state is updated? Sorry if this doesn't make sense, I was having trouble trying to explain the problem. Thanks in advance!
function App() {
var [component, updateView] = useState('ServerFunctions');
var updateDateAndTime = function(formatDate) {
setInterval(function() {
if (document.getElementsByClassName('date')[0] && document.getElementsByClassName('time')[0]) {
updateDate(formatDate('date'));
updateTime(formatDate('time'));
}
}, 1000);
};
useEffect(() => {
updateDateAndTime(formatDate);
});
var [date, updateDate] = useState(formatDate('date'));
var [time, updateTime] = useState(formatDate('time'));
switch(component) {
case 'Welcome':
return (<Welcome updateView={updateView} date={date} time={time} backspacePinpad={backspacePinpad} />);
case 'ServerFunctions':
return (<ServerFunctions updateView={updateView} date={date} time={time} />);
default:
return null;
}
}
class TablesAndInfo extends React.Component {
sections = [[['info-row pct-space-b', 'flex between full-h'], {
1: ['Menu', 'button', 'gray white-f clickable roundish quarter-w label clickable'],
2: [this.props.current, 'div', 'f-override white-b small left three-quarter-w no-txt-overflow'],
}], [['info-table full-h', 'flex full-h'], {
1: ['Another Round', 'button', 'info-button blue white-f clickable'],
2: ['Select All', 'button', 'info-button gray white-f clickable'],
3: ['Name Check', 'button', 'info-button yellow clickable'],
}], [['tables-section full-h', 'tables-section full-h white-b'], {
}], [['new-table-b full-h', 'new-table-b med single round label full-h full-w'], {
1: ['New Table', 'button', 'blue white-f med single clickable round label clickable full-h full-w']
}]];
renderEls(num, classes) {
return (
<div className={classes}>
{this.sections[num].map((child, key) => {
if (typeof child === 'object' && !(child instanceof Array)) {
return (
<div className={this.sections[num][0][0]}>{this.renderSection(child, this.sections[num][0][1], key)}</div>
)
} else {
return null;
}
})}
</div>
)
}
renderSection(obj, parentClass) {
return (
<div className={parentClass}>
{Object.keys(obj).map((key, i) => {
if (obj[key][1] === 'button') {
return (
<button key={i} className={"flex center " + obj[key][2]}>{obj[key][0]}</button>
)
} else {
return (
<div key={i} className={"flex center " + obj[key][2]}>{obj[key][0]}</div>
)
}
})}
</div>
)
}
render() {
return (
<div className="tables space-r">
<div className="info tables-section">
{this.renderEls(0, 'info-table info-r')}
{this.renderEls(1, 'info-table info-b')}
</div>
{this.renderEls(2, 'table-view tables-section full-h pct-space-b')}
{this.renderEls(3, 'new-table')}
</div>
)
}
class ServerFunctions extends React.Component {
return (
<div className="App ServerFunctions">
<Header signOff={this.signOff} renderBttnRow={this.renderBttnRow} />
<div className="container order-control flex space-b">
<SelectedItems />
<TablesAndInfo current={this.state.current} date={this.props.date} time={this.props.time} />
<Functions current={this.state.current} />
</div>
<Footer current={this.state.current} renderBttnRow={this.renderBttnRow} />
</div>
)
}
}
Ended up solving this! Here's what I added in the TablesAndInfo Component:
constructor(props) {
super(props);
this.state = {current: this.props.current, date: this.props.date, time: this.props.time}
}
shouldComponentUpdate(nextProps) {
if ((nextProps.current !== this.state.current) || (nextProps.date !== this.state.date) || (nextProps.time !== this.state.time)) {
this.setState({current: nextProps.current});
this.setState({date: nextProps.date});
this.setState({time: nextProps.time});
}
return true;
}
componentDidUpdate() {
this.sections[0][1][2][0] = this.state.current;
this.sections[0][2][1][0] = this.state.time;
this.sections[0][2][2][0] = this.state.date;
}

How to make a simple loop slider in the React?

Sorry for my English)
Do not judge strictly, since I just started working with the react.
I made a simple slider on the react and now I want to make it cyclic.
But I can’t. In my code it seems to be cyclic, but for some reason it skips the last picture.
how can i fix it?
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [
{
id: 1,
name: "Product 1",
price: 50,
q: 0,
category: "Sporting Goods",
images: [
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property04.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg"
],
currentImageIndex: 0,
isCycleMode: false,
cantGoPrev: false,
cantGoNext: true
},
{
id: 2,
name: "Product 2",
price: 70,
q: 0,
category: "Sporting Goods",
images: [
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property04.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg",
"https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg"
],
currentImageIndex: 0,
isCycleMode: false,
cantGoPrev: false,
cantGoNext: true
}
]
};
}
nextSlideHandler = (e, item, index ) => {
let arr = [...this.state.data];
let newIndex = this.state.data[index].currentImageIndex;
if (e.currentTarget.dataset.direction === "next") {
if (newIndex < this.state.data[index].images.length - 1) {
newIndex = this.state.data[index].currentImageIndex + 1;
arr[index].cantGoPrev = true;
this.setState({data:arr})
}
if (newIndex === this.state.data[index].images.length - 1) {
newIndex = 0;
arr[index].cantGoNext = true;
this.setState({data:arr})
}
} else {
if (newIndex > 0) {
newIndex = this.state.data[index].currentImageIndex - 1;
arr[index].cantGoNext = true;
this.setState({data:arr})
}
if (newIndex === 0) {
arr[index].cantGoPrev = false;
this.setState({data:arr})
}
}
arr[index].currentImageIndex = newIndex;
this.setState({ data:arr });
}
render() {
return (
<div className="App">
<div>
<h3>Products</h3>
<div className="collection">
{this.state.data.map((item, index) => (
<div key={item.id} className="product">
<div className="product__image">
<div>
<button
disabled={!item.cantGoPrev}
data-direction="prev"
onClick={(e)=> this.nextSlideHandler(e,item, index)}
className="prev"
>
prev
</button>
</div>
<div>
<img
src={item.images[item.currentImageIndex]}
alt=""
/>
{item.images.currentImageIndex}
</div>
<div>
<button
disabled={!item.cantGoNext}
data-direction="next"
onClick={(e)=> this.nextSlideHandler(e, item, index)}
className="next"
>
next
</button>
</div>
</div>
<div className="product__name">{item.name}</div>
<div className="product__price">{item.price}</div>
</div>
))}
</div>
</div>
</div>
);
}
}
What is the best way to write a slider?
I will be glad of any help
First: There are many ways to achieve what you are trying to do, but this is how I would have done it.
Instead of using index to update different state, I would make a own component for Product. Inside that component you have full access to that products state and props. This makes it easier to work with the correct data.
I would also remove the next/previous-logic from the state and just do a check if the buttons should be active on render.
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
data: [
{
id: 1,
name: 'Product 1',
price: 50,
q: 0,
category: 'Sporting Goods',
images: [
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property04.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg'
],
currentImageIndex: 0,
isCycleMode: false
},
{
id: 2,
name: 'Product 2',
price: 70,
q: 0,
category: 'Sporting Goods',
images: [
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property04.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property02.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property01.jpg',
'https://ihatetomatoes.net/demos/_rw/01-real-estate/tn_property03.jpg'
],
currentImageIndex: 0,
isCycleMode: false
}
]
}
}
handleChange = (arr) => {
// State updates based on other state should be asynchronous
// https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
this.setState((state, props) => {
const oldArr = [...state.data]
const arrIndex = oldArr.findIndex(x => x.id === arr.id)
oldArr[arrIndex] = arr
return ({
data: oldArr
})
})
}
render () {
return (
<div className='App'>
<div>
<h3>Products</h3>
<div className='collection'>
{this.state.data.map((item) => (
<Product
item={item}
key={item.id}
onChange={this.handleChange}
/>
))}
</div>
</div>
</div>
)
}
}
class Product extends React.Component {
handleSlideChange = (e) => {
const arr = { ...this.props.item }
if (e.currentTarget.dataset.direction === 'next') {
arr.currentImageIndex++
} else {
arr.currentImageIndex--
}
this.props.onChange(arr)
};
render () {
const { item } = this.props
return (
<div key={item.id} className='product'>
<div className='product__image'>
<div>
<button
disabled={item.currentImageIndex <= 0}
data-direction='prev'
onClick={this.handleSlideChange}
className='prev'
>
Prev
</button>
</div>
<div>
<img src={item.images[item.currentImageIndex]} alt='' />
{item.images.currentImageIndex}
</div>
<div>
<button
disabled={item.currentImageIndex >= item.images.length - 1}
data-direction='next'
onClick={this.handleSlideChange}
className='next'
>
Next
</button>
</div>
</div>
<div className='product__name'>{item.name} {item.currentImageIndex}</div>
<div className='product__price'>{item.price}</div>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('root'))
<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>

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

Change color of selected element - React

I'm new to React.
I'm trying to change the color of one particular "li" that was selected, but instead it changes color of all "li".
Also when another "li" is clicked I want the first "i" to be not active again.
here is the code: http://codepen.io/polinaz/pen/zNJKqO
var List = React.createClass({
getInitialState: function(){
return { color: ''}
},
changeColor: function(){
var newColor = this.state.color == '' ? 'blue' : '';
this.setState({ color : newColor})
},
render: function () {
return (
<div>
<li style={{background:this.state.color}} onClick={this.changeColor}>one</li>
<li style={{background:this.state.color}} onClick={this.changeColor}>two</li>
<li style={{background:this.state.color}} onClick={this.changeColor}>three</li>
</div>
);
}
});
ReactDOM.render(
<List/>,
document.getElementById('app')
);
Since you don't have any identifiers on you list items you activate/deactivate them all every time. You need to reference each of them in a different way, then you can set the color individually. This is one example
var List = React.createClass({
getInitialState: function(){
return { active: null}
},
toggle: function(position){
if (this.state.active === position) {
this.setState({active : null})
} else {
this.setState({active : position})
}
},
myColor: function(position) {
if (this.state.active === position) {
return "blue";
}
return "";
},
render: function () {
return (
<div>
<li style={{background: this.myColor(0)}} onClick={() => {this.toggle(0)}}>one</li>
<li style={{background: this.myColor(1)}} onClick={() => {this.toggle(1)}}>two</li>
<li style={{background: this.myColor(2)}} onClick={() => {this.toggle(2)}}>three</li>
</div>
);
}
});
ReactDOM.render(
<List/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app">
<!-- This div's content will be managed by React. -->
</div>

How to implement a toggle effect with react js?

I have been searching for a long time in google. But I haven't found anything. I am looking for a way to implement a toggle effect with reactjs.
Please have a look at my code below.
var Demo = React.createClass({
getInitialState:function(){
return {show:false};
},
onClick:function(){
this.setState({show:true});
},
render: function(){
return (
<div>
<div className="demo" onClick={this.onClick}>
Demo
{this.state.show?<Demosub />:null}
</div>
<div className="demo" onClick={this.onClick}>
Demo
{this.state.show?<Demosub />:null}
</div>
<div className="demo" onClick={this.onClick}>
Demo
{this.state.show?<Demosub />:null}
</div>
</div>
);
}
});
var Demosub = React.createClass({
render: function(){
return (
<div>Demo sub</div>
);
}
});
I would encapsulate each item in its own component like that:
var Demo = React.createClass({
render: function() {
return (
<div>
<DemoItem />
<DemoItem />
<DemoItem />
</div>
);
}
});
var DemoItem = React.createClass({
getInitialState: function() {
return { show: false };
},
toggleShow: function() {
this.setState({ show: !this.state.show });
},
render: function() {
return (
<div className="demo" onClick={this.toggleShow}>
Demo
{this.state.show ? <DemoSub /> : null}
</div>
);
}
});
var DemoSub = React.createClass({
render: function() {
return <div>Demo sub</div>
}
});
import React, { Component } from 'react';
class Person extends Component {
state={
showPerson:false,
}
toggleName=()=>{
const doesShow = this.state.showPerson;
this.setState({
showPerson:!doesShow
})
}
render() {
let personList = null;
if(this.state.showPerson) {
personList = (
<div> Show Content </div>
)
}
return (
<div>
<button onClick={this.toggleName}>Switch</button>
{personList}
</div>
);
}
}
export default Person;

Categories