Rotating background color in ReactJS - reactjs

I have this code in my JS folder...
var bgColors = {
"Default": "#81b71a",
"Blue": "#00B1E1",
"Cyan": "#37BC9B",
"Green": "#8CC152",
"Red": "#E9573F",
"Yellow": "#F6BB42"
};
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div>
<Helmet>
<style>{'body { background-color: red; }'}</style>
</Helmet>
</div>
);
}
}
render(<App />, document.getElementById('root'));
As you can see. the background is set to red. How do I make the background color rotate colors every second or so? I want the colors to rotate through the list of colors I established.

var bgColors = {
default: "#81b71a",
blue: "#00B1E1",
cyan: "#37BC9B",
green: "#8CC152",
red: "#E9573F",
yellow: "#F6BB42",
};
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
bgColor: bgColors.default,
};
this.interval = setInterval(() => {
let randomColor = bgColors[
Object.keys(bgColors)[
Math.floor(Math.random() *
Object.keys(bgColors).length)
]
];
this.setState(() => ({bgColor: randomColor}))
}, 1000);
}
componentWillUnmount() {
clearInterval(this.interval)
}
render() {
return (
<div
style={{
height: '200px',
backgroundColor: this.state.bgColor
}}
>
Background color changes every second
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<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="root"></div>

Related

ReactJS: can not change style with changing state

I'm new in ReactJS(in fact I'm learning), I've written a simple code to check the style changing but as my best knowledge when the state change in react it will reRender the component but when I did this it does not happen, so I tried forceUpdate() and this work but the style does not change again,
I've tried this before with a simple state and it worked but when I set my style in an object everything got screwed up, thanks for any help
class Check extends React.Component {
constructor(props) {
super(props);
this.state = {
sty: {
width: 200 + 'px',
backgroundColor: 'blue',
height: 200 + 'px', marginBottom: 20 + 'px'
}
}
this.update = this.update.bind(this);
}
update() {
let sty = this.state.sty;
sty.backgroundColor = 'red';
this.setState = ({
sty
})
this.forceUpdate();
}
render() {
console.error(this.state.sty['backgroundColor']);
return (
<div style={this.state.sty} onClick={this.update} id="checkBox" className="First">
<span>{this.props.children}</span>
</div>
)
}
}
ReactDOM.render(
<div>
<Check key={1}>1</Check>
<Check key={2}>2</Check>
<Check key={3}>3</Check>
<Check key={4}>4</Check>
</div>,
document.getElementById('container'))
not use =.Use this.setState({...})
https://reactjs.org/docs/react-component.html#setstate
class Check extends React.Component{
constructor(props) {
super(props);
this.state = {
sty : { width : 200 +'px',
backgroundColor : 'blue',
height: 200 + 'px', marginBottom : 20+'px' }
}
this.update = this.update.bind(this);
}
update(){
this.setState(prevState=>({sty:{...prevState.sty,backgroundColor:'red'}}))
}
render() {
console.error(this.state.sty['backgroundColor']);
return (
<div style={this.state.sty} onClick={this.update} id="checkBox" className="First">
<span>{this.props.children}</span>
</div> )
}
}
ReactDOM.render(
<div>
<Check key={1}>1</Check>
<Check key={2}>2</Check>
<Check key={3}>3</Check>
<Check key={4}>4</Check>
</div>, document.getElementById('container'))
In a React component, setState is a function, you have to call it to use it.
Here is a working example of your code :
class Check extends React.Component {
constructor(props) {
super(props);
this.state = {
sty: {
width: 200 + 'px',
backgroundColor: 'blue',
height: 200 + 'px', marginBottom: 20 + 'px'
}
}
}
update = () => {
this.setState({ sty: {
width: 200 + 'px',
backgroundColor: 'red',
height: 200 + 'px', marginBottom: 20 + 'px'
}
});
}
render() {
return (
<div style={this.state.sty} onClick={this.update} id="checkBox" className="First">
<span>{this.props.children}</span>
</div>
)
}
}
ReactDOM.render(
<div>
<Check key={1}>1</Check>
<Check key={2}>2</Check>
<Check key={3}>3</Check>
<Check key={4}>4</Check>
</div>,
document.getElementById('container'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.1.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.1.0/umd/react-dom.production.min.js"></script>
<div id='container'/>
A good practice would rather be to use CSS styling and make your components className vary based on his state

Show or Hide a particular element in react

I have to show list of faqs and I need to hide the answers of the questions. When I click on the question, the answer for that particular question need to be shown. My problem is, I have a bunch of questions and when i click the button, it will show all of the answer instead of the specific answer to that question.
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
isHidden: true
}
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
})
}
render() {
return (
<div>
<span onClick={() => this.toggleHidden()}><strong>This is the question</strong></span>
{!this.state.isHidden && <p>Answer for the question</p>} <br/>
<span onClick={() => this.toggleHidden()}><strong>Question2</strong></span>
{!this.state.isHidden && <p>Answer2</p>} <br/>
<hr></hr>
</div >
)
}
}
You can break your component to one more level to have a sub component which renders only the question and corresponding answer. Pass the question and answers as props. In that way you can use the same component for all questions and yet every question/answer pair will have their own state.
class Faq extends Component{
state = {isHidden: true}
toggleHidden = ()=>this.setState((prevState)=>({isHidden: !prevState.isHidden}))
render(){
return(
<div>
<span onClick={this.toggleHidden}>
<strong>{props.question}</strong></span>
{!this.state.isHidden && <p>{props.answer}</p>}
</div>
)
}
}
class Faqs extends Component {
render() {
return (
<div>
<Faq question={"Question 1"} answer={"answer 1"} />
<Faq question={"Question 2"} answer={"answer 2"} />
</div >
)
}
}
Ideally you would list FAQs in some kind of list - then as you iterate over them, each will have an index number assigned to it - then as you toggle individual answers, you store that index in the state and operate on DOM via that number.
edit. In current day and age, it's only appropriate to show example using hooks:
const {useState} = React;
const FaqApp = () => {
const [ selectedQuestion, toggleQuestion ] = useState(-1);
function openQuestion(index) {
toggleQuestion(selectedQuestion === index ? -1 : index);
}
const faqs = getFaqs();
return (
<div>
<h2>FAQs:</h2>
{faqs.map(( { question, answer}, index) => (
<div key={`item-${index}`} className={`item ${selectedQuestion === index ? 'open' : ''}`}>
<p className='question' onClick={() => openQuestion(index)}>{question}</p>
<p className='answer'>{answer}</p>
</div>
))}
</div>
)
}
function getFaqs() {
const faqs = [
{
question: 'Question 1',
answer: 'answer 1'
},
{
question: 'Question 2',
answer: 'answer 2'
}
];
return faqs;
}
ReactDOM.render(
<FaqApp />,
document.getElementById("react")
);
body {
background: #fff;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
h2 {
margin-bottom: 11px;
}
.item + .item {
margin-top: 11px;
}
.question {
font-weight: bold;
cursor: pointer;
}
.answer {
display: none;
}
.open .answer {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>
older version of this post:
I've written a quick example that allows you to have multiple questions:
class FaqApp extends React.Component {
constructor(props) {
super(props)
this.state = {
// start the page with all questions closed
selectedQuestion: -1
};
this.openQuestion = this.openQuestion.bind(this);
}
getFaqs() {
// some service returning a list of FAQs
const faqs = [
{
question: 'Question 1',
answer: 'answer 1'
},
{
question: 'Question 2',
answer: 'answer 2'
}
];
return faqs;
}
openQuestion(index) {
// when a question is opened, compare what was clicked and if we got a match, change state to show the desired question.
this.setState({
selectedQuestion: (this.state.selectedQuestion === index ? -1 : index)
});
}
render() {
// get a list of FAQs
const faqs = this.getFaqs();
return (
<div>
<h2>FAQs:</h2>
{faqs.length && faqs.map((item, index) => (
<div key={`item-${index}`} className={`item ${this.state.selectedQuestion === index ? 'open' : ''}`}>
<p className='question' onClick={() => this.openQuestion(index)}>
{item.question}
</p>
<p className='answer'>
{item.answer}
</p>
</div>
))}
</div>
)
}
}
ReactDOM.render(<FaqApp />, document.querySelector("#app"))
body {
background: #20262E;
padding: 20px;
font-family: Helvetica;
}
#app {
background: #fff;
border-radius: 4px;
padding: 20px;
transition: all 0.2s;
}
h2 {
margin-bottom: 11px;
}
.item + .item {
margin-top: 11px;
}
.question {
font-weight: bold;
cursor: pointer;
}
.answer {
display: none;
}
.open .answer {
display: block;
}
<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"></div>
The issue is that you're using one boolean piece of state to control the logic for multiple pieces. This is a classic scenario to use separate components.
Create a new component ToggleQuestion that encapsulates the mechanic of show/reveal.
The Faqs component instead manages a list of ToggleQuestion components.
const QUESTIONS = [
{ title: 'q1', answer: 'a1' },
{ title: 'q2', answer: 'a2' }
]
class ToggleQuestion extends React.Component {
constructor (props) {
super(props)
this.state = { isHidden: true }
}
toggleHidden () {
this.setState({ isHidden: !this.state.isHidden })
}
render () {
const { question, answer } = this.props
const { isHidden } = this.state
return (
<div>
<span>{question}</span>
{ !isHidden && <span>{answer}</span> }
<button onClick={this.toggleHidden.bind(this)}>
Reveal Answer
</button>
</div>
)
}
}
class Faqs extends React.Component {
render () {
return (
<div>
{ QUESTIONS.map(question => (
<ToggleQuestion
question={question.title}
answer={question.answer}
/>
))}
</div>
)
}
}
ReactDOM.render(<Faqs />, document.getElementById('container'))
<div id='container'></div>
<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>
I would write a different handler for the answer. In the future if you need more logic for the answer will be scalable. Notice renderAnswer
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
isHidden: true
}
}
toggleHidden () {
this.setState({
isHidden: !this.state.isHidden
})
}
renderAnswer() {
if (this.state.isHidden) {
return;
}
return (
<p>Answer</p>
);
}
render() {
return (
<div>
<span onClick={() => this.toggleHidden()}><strong>This is the question</strong></span>
{ this.renderAnswer() } <br/>
<span onClick={() => this.toggleHidden()}><strong>Question2</strong></span>
{ this.renderAnswer() } <br/>
<hr></hr>
</div >
)
}
}
This is another way to do what you want. (This one will only make it possible to have one open at a time)
class Faqs extends Component {
constructor(props){
super(props);
this.state = {
hiddenId: null,
}
}
setHiddenId(id) {
this.setState({
hiddenId: id
})
}
render() {
return (
<div>
<span onClick={() => this.setHiddenId('one')}><strong>This is the question</strong></span>
{this.state.hiddenId === 'one' && <p>Answer for the question</p>} <br/>
<span onClick={() => this.setHiddenId('two')}><strong>Question2</strong></span>
{this.state.hiddenId === 'two' && <p>Answer2</p>} <br/>
<hr></hr>
</div >
)
}
}

Navigation menu not working in React

Please help me to fix this navigation menu.Something here is not working.It has to change the clicked cell after click. I would be very grateful if you show me where is the problem
class MenuExample extends React.Component{
constructor(props) {
super(props);
this.state = {focused: 0};
}
clicked(index){
this.setState({focused: index});
};
render: {
return (
<div>
<ul>{ this.props.items.map(function(m, index){
var style = '';
if(this.state.focused == index){ style = 'focused'; }
return <li className={style} onClick={this.clicked.bind(this)}>{m}</li>;
}) }
</ul>
<p>Selected: {this.props.items[this.state.focused]}</p>
</div>
);
}
};
ReactDOM.render(
<MenuExample items={ ['Home', 'Services', 'About', 'Contact us'] } />,
document.getElementById('root')
);
Its a binding issue, you forgot to bind the map callback method, here:
this.props.items.map(function(m, index){.....})
Use arrow function to maintain the context, like this:
this.props.items.map((m, index) => {.....})
Check the working code:
class MenuExample extends React.Component{
constructor(){
super();
this.state = { focused: 0 };
}
clicked(index){
this.setState({focused: index});
}
render() {
return (
<div>
<ul>{ this.props.items.map((m, index) => {
var style = '';
if(this.state.focused == index){
style = 'focused';
}
return <li className={style} onClick={this.clicked.bind(this, index)}>{m}</li>
}) }
</ul>
<p>Selected: {this.props.items[this.state.focused]}</p>
</div>
);
}
}
ReactDOM.render(
<MenuExample items={ ['Home', 'Services', 'About', 'Contact us'] } />,
document.getElementById('container')
);
* {
padding:0;
margin:0;
}
html{
font:14px normal Arial, sans-serif;
color:#626771;
background-color:#fff;
}
body{
padding:60px;
text-align: center;
}
ul{
list-style:none;
display: inline-block;
}
ul li{
display: inline-block;
padding: 10px 20px;
cursor:pointer;
background-color:#eee;
color:#7B8585;
transition:0.3s;
}
ul li:hover{
background-color:#beecea;
}
ul li.focused{
color:#fff;
background-color:#41c7c2;
}
p{
padding-top:15px;
font-size:12px;
}
<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='container'/>
Working Fiddle.

How do I add an image to the DOM after another image has loaded?

I want to make sure images are loaded in the right order: first the primary image, then the secondary image. My plan is to inject the secondaryImage once the primary image is done.
class HoverImage extends Component {
constructor (props) {
super(props)
this.state = { secondaryImage: null }
}
primaryImageLoaded () {
//here I would like inject <img className='img-responsive' src={stripUrl(secondaryImage)} /> before primaryImage
}
render () {
const primaryImage = this.props.primaryImage
const secondaryImage = this.props.secondaryImage
if (secondaryImage) {
return (
<div style={{position: 'relative'}}>
<img
className='img-responsive'
src={stripUrl(primaryImage)}
onLoad={this.primaryImageLoaded.bind(this)}
style={{
':hover': {
opacity: 0
},
position: 'absolute',
top: 0}}
/>
</div>
)
}
}
other solutions that create the same effect are fine too!
Try this:
class HoverImage extends Component {
constructor (props) {
super(props)
this.state = {
secondaryImage: null,
showSecondaryImage: false,
}
}
primaryImageLoaded () {
this.setState({showSecondaryImage: true});
}
render () {
const primaryImage = this.props.primaryImage;
const secondaryImage = this.props.secondaryImage;
secondaryImage ?
return (
<div style={{position: 'relative'}}>
{this.state.showSecondaryImage ?
<img className='img-responsive' src={stripUrl(secondaryImage)} />
: <div/>}
<img
className='img-responsive'
src={stripUrl(primaryImage)}
onLoad={this.primaryImageLoaded.bind(this)}
style={{
':hover': {
opacity: 0
},
position: 'absolute',
top: 0
}}
/>
</div>
)
: return <div/>
}
}
jsfiddle link: http://jsfiddle.net/d7hwzapc/
class HoverImage extends Component {
constructor (props) {
super(props)
this.state = {
firstImageLoaded: false,
};
}
componentDidMount() {
this.setState({ firstImageLoaded: true });
}
loadSecondImage() {
if(this.state.firstImageLoaded) {
return (<img
className='img-responsive'
src={stripUrl(this.props.secondaryImage)}
/>);
}
}
render () {
return (
<div style={{position: 'relative'}}>
<img
className='img-responsive'
src={stripUrl(this.props.primaryImage)}
onLoad={this.setState({ firstImageLoaded: true })}
style={{
':hover': {
opacity: 0
},
position: 'absolute',
top: 0}}
/>
{this.loadSecondImage()}
</div>
)
}
When the initial mount is done, it will set a flag in the state which will trigger a re-render.
Hope that helps!
ps: this answer is in no way perfect but should get what you wanted done.

Render the same component twice on onClick in react

I am writing an electron application where I am using react for the UI. I am trying to add shapes(rectangle,square...), so I have created components for each of the shapes. And I have a list of shapes, when I click on the list the corresponding shapes are added. But I want to add the same shape twice which I am not able to do. Can someone help me here?
Below is my code.
List.js
import React from 'react';
class List extends React.Component{
render(){
return (
<div>
<li onClick={this.props.drawSquare}>Square</li>
<li onClick={this.props.drawRectangle}>Rectangle</li>
<li onClick={this.props.drawCircle}>Circle</li>
</div>
);
}
}
export default List
AppContainer.js
import React from 'react'
import List from '../components/List'
import Square from '../components/Square'
import Rect from '../components/Rect'
import Cir from '../components/Cir'
import But from '../components/basic/button'
const style={
position: 'fixed',
width: '800',
height: '800'
};
const butStyle={
position: 'relative',
top: '500px'
}
const style1={
borderStyle: 'groove',
position: 'fixed',
width: '500',
height: '500'
};
class AppContainer extends React.Component{
constructor(props) {
super(props);
this.state={squareclicked:0,
rectClicked:0,
circleClicked:0,};
}
drawSquare(){
console.log("inside square function");
this.setState({squareclicked:this.state.squareclicked+1})
console.log(this.state.squareclicked);
}
drawRectangle(){
console.log("inside rect function");
this.setState({rectClicked:this.state.rectClicked+1})
}
drawCircle(){
console.log("inside circle function");
this.setState({circleClicked:this.state.circleClicked+1})
}
render(){
console.log('render called');
return (
<div style={style}>
<div id="mainAppDiv" >
<List drawSquare={this.drawSquare.bind(this)}
drawRectangle={this.drawRectangle.bind(this)}
drawCircle={this.drawCircle.bind(this)}/>
<div id="shapeConatinerDiv" style={style1}>
{this.state.squareclicked}
{this.state.squareclicked > 0 && (<Square/>)}
{this.state.circleClicked > 0 && (<Cir/>)}
{this.state.rectClicked > 0 && (<Rect/>)}
</div>
</div>
<div style={butStyle}>
<But/>
</div>
</div>
);
}
}
export default AppContainer
Square.js
import React from 'react';
import ReactDOM from 'react-dom';
import {Rectangle} from 'react-shapes';
import Rnd from 'react-rnd'
import Modal from 'react-bootstrap/lib/Modal'
import ColorPallete from './Badging/ColorPalette'
import Button from 'react-bootstrap/lib/Button'
const style = {
border: 'solid 1px',
};
const style1={
position: 'fixed',
width: '500',
height: '500'
};
class Square extends React.Component{
constructor(props) {
super(props);
this.state={w:100,
h:100,
col:{color:'#ff0000'},
zIndex: 99,
modalShow: false,
};
}
close(){
this.setState({modalShow: false});
}
onDrag(){
console.log('hi');
}
onResi(dir, styleSize, clientSize, delta){
this.setState({w:clientSize.width});
this.setState({h:clientSize.height});
}
editSquare(){
this.setState({ modalShow: true });
}
render(props) {
return (
<Rnd ref={c => { this.rnd = c; }}
initial={{
x: parent.innerWidth / 2 - 700,
y: parent.innerHeight / 2 - 80,
width: this.state.w,
height: this.state.h,
}}
style={style}
minWidth={this.state.w}
minHeight={this.state.h}
maxWidth={500}
maxHeight={500}
bounds={'parent'}
lockAspectRatio={true}
onResize={this.onResi.bind(this)}
onDrag={this.onDrag.bind(this)}
>
<Rectangle width={this.state.w} height={this.state.h} fill={this.state.col} stroke={{color:'#E65243'}} strokeWidth={1} onClick={this.editSquare.bind(this)}/>
</Rnd >
);
}
}
export default Square
And the other shapes have the same kind of code.
Right now I am able to add only one square and when I click again nothing happens. But I am able to add other shapes which is once.
You'll want to add elements to an array and render the array of elements.
Here's some rough code that might help:
Component {
constructor() {
super(props)
this.state = { elements: [] }
}
render() {
return (<div>
<div onClick={()=>this.add()}>Add</div>
<div>{this.state.elements}</div>
</div>)
}
add() {
this.setState({
elements: this.state.elements.push(<div id={elements.length}>Element</div>)
})
}
}

Resources