Show/Hide React Component based on State - javascript

I am very new to React and am trying to create a page where clicking on the color square will show the hex code for that color. I've tried a bunch of different things and I can't figure out if my problem is in the event handling, in the state handling, both, or in something else altogether. I can get the hex code to either be there or not, but not have it change when I click.
Here is my main:
<main>
<h1>Dynamic Hex Code Display</h1>
<div id="container"></div>
<script type="text/babel">
class ColorSquare extends React.Component {
render() {
var blockStyle = {
height: 150,
backgroundColor: this.props.color,
};
return <div style={blockStyle} onClick = {this.props.onClick}></div>;
}
}
class HexDisplay extends React.Component {
render() {
var hexText = {
fontFamily: "arial",
fontWeight: "bold",
padding: 15,
margin: 0,
textAlign: "center",
};
var hexTextVis = {
...hexText,
visibility: "visible"
}
var hexTextInvis = {
...hexText,
visibility: "hidden"
}
var isVisible = this.props.isVisible;
if (isVisible) {
return <p style={hexTextVis}>{this.props.color}</p>;
} else {
return <p style={hexTextInvis}>{this.props.color}</p>;
}
}
}
class HexParent extends React.Component {
constructor(props) {
super(props);
this.state = {
isVisible: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
this.setState(currentVis => ({isVisible: !currentVis.isVisible}));
console.log(this.state);
console.log('clicking');
}
render() {
var fullBoxStyle = {
padding: 0,
margin: 10,
backgroundColor: "#fff",
boxShadow: "3px 3px 5px #808080",
boxRadius: "5px 5px",
height: 200,
width: 150,
};
var buttonStyle = {
width:150,
backgroundColor: this.props.color
}
return (
<div style={fullBoxStyle}>
<span onClick={(e) => this.handleClick()}>
<ColorSquare color={this.props.color} />
<span style={{
isVisible: this.state.isVisible ? "true" : "false",
}}>
<HexDisplay color={this.props.color} />
</span>
</span>
</div>
);
}
}
ReactDOM.render(
<div class="colorRow">
<HexParent color="#ba2c9d" />
<HexParent color="#2cba90" />
<HexParent color="#2c9dba" />
</div>,
document.querySelector("#container")
);
</script>

When the object is created, it's a hexTextVis object. When you click, isVisible changes, but it's still a hexTextVis object and so the render doesn't change. You could either do something like:
<HexDisplay visibility={state.isVisible}/>
or
{state.isVisible ? <div/> : <HexDisplay />}

style={{
isVisible: this.state.isVisible ? "true" : "false",
}}
There isn't a css property with this name. Perhaps you meant to use visibility?
style={{
visibility: this.state.isVisible ? "visible" : "hidden"
}}

Try wrapping the span and and using a ternary operator to render the span element, based on if the condition of isVisible is equal to true, otherwise it should not return anything
{this.state.isVisible && <span><HexDisplay /></span>}

Related

Reactjs, Styling each element of array with different styles

I want to create an array with some elements and then iterate (with .forEach or .map) it.
but each of array elements must have different style. for example I have an array like that:
["johnny red", "Stephanie blue", "Hans green", "Fifty Shades Of grey :d"]
also, I want reuse some of array's individual elements in another component.
how can i do that?
(imagine that last word in each element is a individual style e.g. background-color or color,)
Can you help me?
please give me an advice, what would I do?
There are many ways to achieve this, the key difference is how you are representing your value-style pairs.
Eventually, you need to map the values to their styles.
For example:
const myStyles = {
'johnny red': { color: 'red' },
'Stephanie blue': { color: 'blue' },
'Hans green': { color: 'green' },
'Fifty Shades Of grey :d': { color: 'pink' }
};
export default function App() {
return (
<FlexBox>
<FlexItem>
{Object.entries(myStyles).map(([key, style]) => (
<div key={key} style={style}>
{key}
</div>
))}
</FlexItem>
</FlexBox>
);
}
It's not very clear what you want, but you can attach styles to components like this:
const values = [
{
text: "one",
css: { color: 'blue' }
},
{
text: "two",
css: { color: 'red' }
},
];
const Test = props => {
const { values } = props;
return (
<div>{values.map(
(value, i) => <div key={i} style={value.css}>{value.text}</div>
)}</div>
);
}
ReactDOM.render(
<Test values={values} />,
document.getElementById("react")
);
<div id="react"></div>
<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>
You mean something like this? The snippet is below and here is the codepen texample: https://codepen.io/tormod17/pen/apvXoW?editors=0010
Also, have you considered incorporating styled components with react? It could help with this project. https://www.styled-components.com/docs/basics
{children.map(element => {
return (
<element.type
{...element.props}
style={{
height: '33%',
}}
/>
)
})}
This is from another project:
import * as React from "react";
import { IAddressListProps } from '../../detailPage/components/interfaces/IAddressListProps';
import { config } from "../../config";
export class PrintAddressList extends React.Component<IAddressListProps, {}>{
constructor(props: IAddressListProps) {
super(props);
}
private createAddressCard = () => {
let parent = [];
this.props.items.map((address) => {
parent.push(<div style={{ padding: '10px', border: '1px solid #ccc', margin: '5px' }}>
<label>{config.colNames.addressList.clmnAddressType}: </label>
<label>{address.Adressart}</label><br />
<label>{config.colNames.addressList.clmnCompanyName}: </label>
<label>{address.Firma}</label><br />
<label>{config.colNames.addressList.clmnPlaceName}: </label>
<label>{address.Ort}</label><br />
<label>{config.colNames.addressList.clmnZipCode}: </label>
<label>{address.PLZ}</label><br />
<label>{config.colNames.addressList.clmnTelephone}: </label>
<label>{address.Telefon}</label><br />
</div>);
});
return parent;
}
public render(): React.ReactElement<IAddressListProps> {
return (
<div>
{this.createAddressCard()}
</div>
);
}
}

How to create sticky header with flexbox and REACT

I have created a header component in REACT and the Header uses flexbox for layout. Now I need to make the Header stick. I tried using position: fixed but that messes up the flexbox styling. Does anyone have any ideas on how I can solve this?
The code is shown below. The height of the header varies depending on whether mobile menu is displayed or not.
Thanks.
import React, { Component } from 'react';
import Logo from './Logo'
import logo from '../images/transparent.png';
import MenuItem from "./MenuItem";
import MenuItemBurger from "./MenuItemBurger";
class Header extends Component {
constructor(props) {
super(props);
this.headerStyle = {
height: 'auto',
padding: 10,
display: 'flex',
justifyContent: 'space-between',
zIndex: 10,
backgroundColor: 'white'
};
this.burgerMenuIconStyle = {
color: '#757c8b',
};
this.mobileMenuStyle = {
zIndex: 20,
justifyContent: 'center',
alignItems: 'center'
};
this.state = {
windowWidth: window.innerWidth,
mobileNavVisible: false,
navItems : [
{text: 'Home', selected: true, id:'home'},
{text: 'Our Services', selected: false, id: 'services'},
{text: 'Contact Us', selected: false, id: 'contact'}
]
};
}
handleResize() {
this.setState({windowWidth: window.innerWidth});
}
componentDidMount() {
window.addEventListener('resize', this.handleResize.bind(this));
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize.bind(this));
}
toggleMenuOnClick() {
if (this.state.mobileNavVisible) {
this.setState({...this.state, mobileNavVisible: false});
}
else {
this.setState({...this.state, mobileNavVisible: true});
}
}
renderMobileHeader() {
const navItemsMappedBurger = this.state.navItems.map(item => <MenuItemBurger text={item.text} id={item.id} onClick={() => this.toggleMenuOnClick()}/>);
if (this.state.mobileNavVisible) {
return (
<div className="mobileHeader">
<div style={this.headerStyle}>
<Logo logo={logo}/>
<i className="fa fa-bars fa-2x" onClick={() => this.toggleMenuOnClick()} style={this.burgerMenuIconStyle}></i>
</div>
<hr></hr>
<div className="navItems" style={this.mobileMenuStyle}> {navItemsMappedBurger} </div>
</div>
)
}
return (
<div className="mobileHeader">
<div style={this.headerStyle}>
<Logo logo={logo}/>
<i className="fa fa-bars fa-2x" onClick={() => this.toggleMenuOnClick()} style={this.burgerMenuIconStyle}></i>
</div>
</div>
)
}
renderWideHeader() {
const navItemsMapped = this.state.navItems.map(item => <MenuItem text={item.text} id={item.id}/>);
return (
<div className="wideHeader" style={this.headerStyle}>
<Logo logo={logo}/>
<div className="navItems">{navItemsMapped}</div>
</div>
)
}
render() {
if (this.state.windowWidth < 1000) {
return (
this.renderMobileHeader()
)
}
return (
this.renderWideHeader()
);
}
};
export default Header;
try to add a container to deal with the fixed position.
Something like this:
this.fixedHeader = {
position: fixed;
width: 100%;
top: 0;
left: 0;
z-index: 1000;
}
const FixedHeader = (children) => {
return <div style={this.fixedHeader}>{children}</div>
}
render() {
if (this.state.windowWidth < 1000) {
return <FixedHeader>{ this.renderMobileHeader() }</FixedHeader>
}
return <FixedHeader>{ this.renderWideHeader() }</FixedHeader>
}

Pop up alert when input is empty in react

I have asked this question many times here but didn't get the answer properly or any complete result. i need to validate my input or i can do that when my input tag is empty or when there is no number in the input, the alert should pop up. I tried for an alert but don't know why it is not working. Please help i'm stuck in this since a week.
Code:
<script type="text/jsx">
var styles = {
margin: '2em auto',
width: '300px',
height: '300px',
backgroundColor: '#DD4814',
color: '#ffffff',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'space-around'
};
var inputs = {
position: 'relative',
bottom: '17%',
left: '20%'
}
var btns = {
position: 'relative',
bottom: '7%'
}
var btn = {
backgroundColor: '#ffffff',
color: '#000000',
borderColor: '#DEB887',
borderRadius: '0.4em',
cursor: 'pointer',
margin: '0 1em',
padding: '0.5em',
display: 'inline-block'
}
var required = true;
class Timer extends React.Component {
constructor (props) {
super(props)
this.state = {count: 0, customNumber: 0}
}
handleChange (e) {
this.setState({ customNumber: e.target.value});
}
componentWillUnmount () {
clearInterval(this.timer)
}
tick () {
if (this.state.customNumber) {
this.setState({
count: (this.state.customNumber--)
})
if (this.state.customNumber <= 0) {
this.setState({ count: 0})
clearInterval(this.timer)
this.setState({ disabled: false })
}
} else {
this.setState({count: (this.state.count - 1)})
}
}
display () {
return ('0' + this.state.count % 100).slice(-2)
}
startTimer () {
if ((this.state.inputValue == " ") && isNaN(this.state.inputValue))
{
alert("Please give some value in number");
}
clearInterval(this.timer)
this.timer = setInterval(this.tick.bind(this), 1000)
this.setState({ disabled: true })
}
stopTimer () {
clearInterval(this.timer)
}
resetTimer () {
clearInterval(this.timer)
this.setState({count: 0})
this.setState({ disabled: false })
}
render () {
return (
<div style={styles} className='timer'>
<h1 style={{fontSize: '4em'}}>{this.display()}</h1>
<div className="input_text" style={inputs}>
<label htmlFor="custom_number">Enter number to start timer</label>
<input type="text" name="custom_number" id="custom_number" required={required} value={this.state.inputValue} onChange={this.handleChange.bind(this)} disabled={this.state.disabled} placeholder="Enter b/w 1-100" />
</div>
<div style={btns} className="buttons">
<button style={btn} type="button" name="start_btn" id="start_btn" onClick={this.startTimer.bind(this)}>Start</button>
<button style={btn} type="button" name="stop_btn" id="stop_btn" onClick={this.stopTimer.bind(this)}>Pause</button>
<button style={btn} type="button" name="reset_btn" id="reset_btn" onClick={this.resetTimer.bind(this)}>Stop</button>
</div>
</div>
)
}
}
ReactDOM.render(
<Timer />,
document.getElementById('root')
)
</script>
<div id="root"></div>
First thing, using alerts is not the best way to get the user's attention. console.log() is much more effective if all you are doing is debugging your code
Second thing, you are asking for alerts in a timer loop - you could end up with hundreds of alerts this way (refer to my first point)
Third thing, you are checking the value of this.state.inputValue and comparing it to a string containing one space (" ") which doesn't seem right
Fourth thing, you are setting the value of your input field with this:
value={this.state.inputValue}
This basically means the value of the field is set and can't be changed. You probably want to use defaultValue instead
Five, and I'm stopping here, your handleChange method doesn't even set the state, so you will never get what you want anyway.

How to append text to text area created in React JS?

I have the following code which creates a text area.
interface IReceiverProps {
receivedMessage: string;
topic: string;
}
export default class Receiver extends React.Component<IReceiverProps, {}> {
render() {
var textAreaStyle = {
width: 1300,
height: 450,
border: '3px solid #cccccc',
padding: '5px',
fontFamily: 'Tahoma, sans-serif',
overflow: 'auto',
marginLeft: '10px'
}
return (
<textarea style={textAreaStyle} value={this.props.receivedMessage}/>
);
}
}
This received message is passed by another component. How can I append the receivedMessage one below another in this text area? Any help would be much appreciated.
Use a state called textMessage.
constructor(props) {
super(props);
this.state = {
textMessage: props.receivedMessage
};
}
In componentWillReceiveProps, append to textMessage.
componentWillReceiveProps(nextProps) {
if (nextProps.receivedMessage !== this.props.receivedMessage) {
this.setState({
textMessage: `${this.state.textMessage}\n{nextProps.receivedMessage}`
});
}
}
Bind to textMessage.
<textarea style={textAreaStyle} value={this.state.textMessage} />

Change color of react-big-calendar events

I need to make a calendar with events and I decided to use react-big-calendar. But I need to make events of different colors. So each event will have some category and each category has corresponding color. How can I change the color of the event with react?
Result should look something like this
Sorry, I haven't read the documentation really well. It can be done with the help of eventPropGetter attribute. I've made it like this:
eventStyleGetter: function(event, start, end, isSelected) {
console.log(event);
var backgroundColor = '#' + event.hexColor;
var style = {
backgroundColor: backgroundColor,
borderRadius: '0px',
opacity: 0.8,
color: 'black',
border: '0px',
display: 'block'
};
return {
style: style
};
},
render: function () {
return (
<Layout active="plan" title="Planning">
<div className="content-app fixed-header">
<div className="app-body">
<div className="box">
<BigCalendar
events={this.events}
defaultDate={new Date()}
defaultView='week'
views={[]}
onSelectSlot={(this.slotSelected)}
onSelectEvent={(this.eventSelected)}
eventPropGetter={(this.eventStyleGetter)}
/>
</div>
</div>
</div>
</Layout>
);
}
Additional tip on how to style different kinds of events: In the myEvents array of event objects, I gave each object a boolean property isMine, then I defined:
<BigCalendar
// other props here
eventPropGetter={
(event, start, end, isSelected) => {
let newStyle = {
backgroundColor: "lightgrey",
color: 'black',
borderRadius: "0px",
border: "none"
};
if (event.isMine){
newStyle.backgroundColor = "lightgreen"
}
return {
className: "",
style: newStyle
};
}
}
/>
This solution is simple !
eventPropGetter={(event) => {
const backgroundColor = event.allday ? 'yellow' : 'blue';
return { style: { backgroundColor } }
}}
change the condition according to your need and it is done.
Siva Surya's solution is the fastest, and I have added the color property as well. Thanks...
import React, {useEffect, useLayoutEffect} from 'react';
import { Calendar, momentLocalizer,globalizeLocalizer } from 'react-big-calendar'
import moment from 'moment';
import { connect } from 'frontity';
import BackgroundWrapper from 'react-big-calendar/lib/BackgroundWrapper';
const MyCalendar = ({ actions, state, objetoBloque, formato }) => {
const localizer = momentLocalizer(moment);
const myEventsList = [
{
title: 'My Event',
start: '2022-06-21T13:45:00-05:00',
end: '2022-06-25T14:00:00-05:00',
// elcolor:'red'
colorEvento:'red'
},
{
title: 'Otro',
start: '2022-06-15T13:45:00-05:00',
end: '2022-06-23T14:00:00-05:00',
colorEvento:'green',
color:'white'
}
];
return(
<div>
<Calendar
// defaultDate = {defaultDate}
localizer={localizer}
events={myEventsList}
startAccessor="start"
endAccessor="end"
style={{ height: 500 }}
BackgroundWrapper = "red"
eventPropGetter={(myEventsList) => {
const backgroundColor = myEventsList.colorEvento ? myEventsList.colorEvento : 'blue';
const color = myEventsList.color ? myEventsList.color : 'blue';
return { style: { backgroundColor ,color} }
}}
/>
</div>
)
}
export default connect(MyCalendar);
Searching for how to change the border colour of an event also lead me here, and I couldn't find the answer anywhere else, but found that adding the following done the trick:
border: "black",
borderStyle: "solid"

Categories