Given the following code I am struggling to figure out how to set value of button back to original state, after it is clicked once ?
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
/**
* links : https://www.youtube.com/watch?v=GhbhD1HR5vk&t=297s
* https://reactjs.org/docs/handling-events.html
*
*
*
*/
class Input extends Component {
constructor(props) {
super(props);
this.state = {
tagged: false,
user: '',
tag: ''
}
this.handleUserChange = this.handleUserChange.bind(this);
}
handleClick(e) {
this.setState({tagged: true});
e.preventDefault();
console.log('The link was clicked.');
}
handleUserChange(e) {
console.log("e.target.value");
this.setState({user: e.target.value});
}
handleTagChange(e) {
console.log(e.target.value);
this.setState({tag: e.target.value});
}
render() {
return (
<div id="id" style={divStyle}>
<p> hello </p>
<input
style = {textStyle}
placeholder="user#email.com"
type="text"
onChange={ this.handleUserChange.bind(this) }
>
</input>
<input
style = {textStyle}
placeholder="tag"
type="text"
onChange={ (e) => this.handleTagChange(e) }
>
</input>
<button
onClick={(e) => this.handleClick(e)}
style={buttonStyle}>
{this.state.tagged ? 'Tagged' : 'Tag ' }
</button>
<p>
{this.state.tagged ? this.state.user + ' was tagged with ' + this.state.tag : ''}
{/* {this.setState({tagged: false})} */}
</p>
</div>
)
}
}
var divStyle = {
position: 'relative',
top:'50%',
left: '15%',
};
var textStyle = {
margin: '20px 20px 20px 20px',
height: '20px',
width: '200px',
};
var buttonStyle = {
margin: '20px 20px 20px 20px',
background: '#7FFFD4',
color: 'black',
height: '25px',
width: '250px'
};
export default Input;
set your state like this in your handClick method
this.setState((prevState)=> ({
tagged: !prevState.tagged
}));
Related
I'm new to React and been struggling with new challenges. Please write me your opinion and help me to get out of this challenge. I need to take the input value and append it in list area. Basically getting that state.inputValue and append it in ul of listArea.
This is InputTask component.
import React from 'react';
class InputTask extends React.Component {
state = { inputValue: ''}
onInputSubmit = (e) => {
this.setState({inputValue: e.target.value})
}
handleSubmit = (e) => {
e.preventDefault();
console.log('A name was submitted: ' + this.state.inputValue);
}
render() {
return (
<form className="ui input" onSubmit={this.handleSubmit} style={{marginRight:10}}>
<input type="text" value={ this.state.inputValue } onChange={this.onInputSubmit}/>
</form>
)
}
}
export default InputTask;
And this is listArea component.
import React from 'react';
class ListArea extends React.Component{
render() {
const style={
backgroundColor: "#f5d556",
height: "400px",
padding: "40px",
borderRadius: "20px"
};
const listStyle = {
backgroundColor: "green",
color: "white",
listStyle: "none",
textAlign: "left",
padding: "5px",
marginBottom: "10px",
borderRadius: "5px"
}
const iconStyle = {
float: "right"
}
const labelStyle = {
color: "white"
}
return(
<div className="ui form" style={{marginBottom:10}}>
<div className="field">
<div style={style}>
<ul style={{paddingLeft: 0}}>
<li style={listStyle}>
<div className="ui checkbox">
<input type="checkbox" name="example"/>
<label style={labelStyle}> hello there!</label>
</div>
<i className="white trash icon" style={iconStyle}></i>
</li>
</ul>
</div>
</div>
</div>
)
}
}
export default ListArea;
this is App component
import React from 'react';
import ReactDOM from 'react-dom';
import InputTask from "./components/inputTask";
import ListArea from "./components/listArea";
class App extends React.Component {
render() {
return (
<div className="ui container" style={{textAlign:'center'}}>
<h1>Tasks</h1>
<ListArea />
<InputTask />
</div>
);
}
}
ReactDOM.render(<App />,document.getElementById('root'));
In InputTask component at handleSubmit with this.props.InputSelected(this.state.inputValue);
I sent back selected input to it's parent(App.js)
import React from "react";
class InputTask extends React.Component {
state = { inputValue: "" };
onInputSubmit = (e) => {
this.setState({ inputValue: e.target.value });
};
handleSubmit = (e) => {
e.preventDefault();
console.log("A name was submitted: " + this.state.inputValue);
this.props.InputSelected(this.state.inputValue);
this.setState({ inputValue: "" });
};
render() {
return (
<form
className="ui input"
onSubmit={this.handleSubmit}
style={{ marginRight: 10 }}
>
<input
type="text"
value={this.state.inputValue}
onChange={this.onInputSubmit}
/>
</form>
);
}
}
export default InputTask;
In App component I got selected value with handleInputSelected and added it to list to send to ListArea component
import React from "react";
import InputTask from "./components/inputTask";
import ListArea from "./components/listArea";
class App extends React.Component {
state = { list: [] };
handleInputSelected = (input) => {
const { list } = { ...this.state };
list.push(input);
this.setState(list);
};
render() {
return (
<div className="ui container" style={{ textAlign: "center" }}>
<h1>Tasks</h1>
<ListArea list={this.state.list} />
<InputTask InputSelected={(input) => this.handleInputSelected(input)} />
</div>
);
}
}
export default App;
And finally in ListArea component with map on list I just append li element to ul.
import React from "react";
class ListArea extends React.Component {
render() {
console.log("data: ", this.props.data);
const style = {
backgroundColor: "#f5d556",
height: "400px",
padding: "40px",
borderRadius: "20px",
overflow: "scroll"
};
const listStyle = {
backgroundColor: "green",
color: "white",
listStyle: "none",
textAlign: "left",
padding: "5px",
marginBottom: "10px",
borderRadius: "5px"
};
const iconStyle = {
float: "right"
};
const labelStyle = {
color: "white"
};
console.log(this.props.data);
return (
<div className="ui form" style={{ marginBottom: 10 }}>
<div className="field">
<div style={style}>
<ul style={{ paddingLeft: 0 }}>
<li style={listStyle}>
<div className="ui checkbox">
<input type="checkbox" name="example" />
<label style={labelStyle}> hello there!</label>
</div>
<i className="white trash icon" style={iconStyle}></i>
</li>
{this.props.list.map((m) => (
<li style={listStyle}>
<div className="ui checkbox">
<input type="checkbox" name="example" />
<label style={labelStyle}> {m}</label>
</div>
<i className="white trash icon" style={iconStyle}></i>
</li>
))}
</ul>
</div>
</div>
</div>
);
}
}
export default ListArea;
I have a parent component, that dynamically creates child components, and works great. But as part of that child component, I'm trying to open a modal with a button click, yet the button doesn't work.
To me it seems like that the this.props.lgShow isn't getting the state change. How do I make sure of that?
Here's my parent component:
import React, { Component, Fragment } from 'react';
import Button from 'react-bootstrap/Button';
import Policy from './Policy/Policy';
import PolicyButton from './PolicyButton/PolicyButton';
class Handbook extends Component {
constructor(props){
super(props);
this.state = {
clients: [],
policies: [],
usedPolicies: [],
client: 'Choose Client',
logo: '',
color1: '#000',
color2: '#fff',
lgShow: 'false' // show modal toggle
};
this.modalOpen = this.modalOpen.bind(this);
this.modalClose = this.modalClose.bind(this);
this.modalSave = this.modalSave.bind(this);
}
componentDidMount() {
fetch('/api/themes/all')
.then(res => res.json())
.then((result) => {
this.setState({ clients: result });
console.log(result);
})
.then(
fetch(`/api/policy/all`)
.then(res => res.json())
.then((result) => {
this.setState({ policies: result });
console.log(result);
})
);
}
handleDeletePolicy = policyId => {
console.log(`Button clicked: ` + policyId);
for (var i = 0; i < this.state.usedPolicies.length; i++) {
if (this.state.usedPolicies[i].id === policyId) {
const policies = this.state.policies;
const usedPolicies = this.state.usedPolicies;
policies.push(usedPolicies[i]);
this.setState({ policies: policies });
usedPolicies.splice(i, 1);
this.setState({ usedPolicies: usedPolicies });
console.log(this.state.policies);
console.log(this.state.usedPolicies);
}
}
}
modalOpen = policyId => {
console.log("Open Modal" + policyId);
this.setState({lgShow: true});
}
modalClose = policyId => {
console.log("Close Modal" + policyId);
this.setState({ lgShow: false });
}
modalSave = policyId => {
console.log("Save Modal" + policyId);
this.setState({ lgShow: false });
}
render(){
return(
<Fragment>
<div className='policies'>
{this.state.usedPolicies.map(policy => (
<Policy key={policy.id} id={policy.id} policy={policy.policy} contents={policy.contents} color1={this.state.color1} color2={this.state.color2} onDeletePolicy={this.handleDeletePolicy} onOpen={this.modalOpen} onClose={this.modalClose} onSave={this.modalSave} />
))}
</div>
</Fragment>
);
}
}
export default Handbook;
And here is my child component.. I believe the problem must be here somewhere.
import React, { Component } from 'react';
import styled from 'styled-components';
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import TinyEditor from '../../TinyEditor/TinyEditor';
const Div = styled.div `
background-color: white;
color: black;
margin-top: 2em;
.edit{
text-align: right;
svg{
font-size: 1em;
margin: 0.25em;
}
}
.policy{
border: 1px solid black;
padding: 2em;
}
h1{
margin-bottom: 1em;
text-align: left;
padding: .25em;
}
`
class Policy extends Component {
constructor(props){
super(props);
this.state = {
id: this.props.id,
policy: this.props.policy,
contents: this.props.contents,
color1: this.props.color1,
color2: this.props.color2,
lgShow: this.props.lgShow
}
}
render(){
return(
<Div className="container">
<div className="edit">
<Button variant="light" onClick={() => this.props.onOpen(this.props.id)}><i className="far fa-edit"></i></Button>
<Button variant="light" onClick={() => this.props.onDeletePolicy(this.props.id)}><i className="far fa-trash-alt"></i></Button>
</div>
<div className="policy">
<h1 style={{ background: this.props.color1, color: this.props.color2 }}>{this.props.policy}</h1>
<div dangerouslySetInnerHTML={{ __html: this.props.contents }}></div>
</div>
<Modal
size="lg"
show={this.props.lgShow}
onHide={this.props.onClose}
aria-labelledby="modal-title-lg"
>
<Modal.Header closeButton>
<Modal.Title id="modal-title-lg">
Large Modal
</Modal.Title>
</Modal.Header>
<Modal.Body>
<TinyEditor />
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={this.props.onClose}>
Close
</Button>
<Button variant="primary" onClick={this.props.onSave}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</Div>
)
}
}
export default Policy;
I do not see 'lgShow' property in the 'Policy' tag.
<Policy
key={policy.id}
id={policy.id}
policy={policy.policy}
contents={policy.contents}
color1={this.state.color1}
color2={this.state.color2}
onDeletePolicy={this.handleDeletePolicy}
onOpen={this.modalOpen}
onClose={this.modalClose}
onSave={this.modalSave}
/>
In the child element 'Policy' you wrote:
this.state = {
id: this.props.id,
policy: this.props.policy,
contents: this.props.contents,
color1: this.props.color1,
color2: this.props.color2,
lgShow: this.props.lgShow // This one is not in parent element
}
For my app, I use react color picker https://casesandberg.github.io/react-color. I must make add button, and when the user clicks on this button it needs to show div(className is saved-color-placeholder) with the selected color. So, the background of div must be like a selected color. In function saveColor, I push the color in an empty array.
This is my code
class Colorpicker extends React.Component {
constructor(props) {
super(props);
this.state = {
displayColorPicker: false,
color: {
r: '0',
g: '0',
b: '0',
a: '1',
},
colorHex: "#000",
savedColors: []
};
}
handleClick = () => {
this.setState({ displayColorPicker: !this.state.displayColorPicker })
};
handleClose = () => {
this.setState({ displayColorPicker: false })
};
handleChange = (color) => {
this.setState({ color: color })
console.log(color)
};
saveColor = (color) => {
let savedColorsArray = this.state.savedColors;
savedColorsArray.push(this.state.color)
this.setState({
savedColors: savedColorsArray
})
console.log(this.state.savedColors)
}
render() {
const styles = reactCSS({
'default': {
color: {
width: '31px',
height: '31px',
borderRadius: '20px',
background: `rgba(${this.state.color.r}, ${this.state.color.g}, ${this.state.color.b}, ${this.state.color.a})`,
},
popover: {
position: 'absolute',
zIndex: '2',
},
savedColor: {
width: '28px',
height: '28px',
borderRadius: '14px',
marginRight: '8px',
background: `rgba(${this.state.color.r}, ${this.state.color.g}, ${this.state.color.b}, ${this.state.color.a})`
}
},
});
return (
<div className="text-color-container ">
<div className="selected-color-content">
<div className="hex-placeholder">
<p>{this.state.colorHex}</p>
</div>
<div className="switch" onClick={this.handleClick}>
<div style={styles.color} />
</div>
{
this.state.displayColorPicker ?
<div className="wrapper">
<div style={styles.popover}>
<div style={styles.cover} onClick={this.handleClose} />
<SketchPicker color={this.state.color} onChange={this.handleChange} />
<div className="saved-colors">
<span >Saved colors</span>
<div className="painted-colors">
<button onClick={this.saveColor} className="btn-save-color">Add</button>
<span slassName="saved-color-placeholder">
<div style={styles.savedColor}/>
</span>
</div>
</div>
</div>
</div>
:
null
}
</div>
</div>
)
}
}
export default Colorpicker
I am not sure this is the best solution but I think it can be good enough.
You can use arrays inside your style prop. So what you could do is:
<div style={[styles.savedColor,{backgorundColor: selectedColor}]>
Hope this will helps.
New to react and trying to use in a new electron learning project I have. I'm trying to build a really basic drawing app.
I created a ToolbarButton class. That would represent each button and a Toolbar that would manage the button group. Example If you pick a 'primary' tool then it should turn off all other primary tools and leave only your current selection.
In jQuery I'd just do something like
let button = $(this);
let toolbar = $(this).parent();
toolbar.find('button.toolbar-button').removeClass('active');
button.addClass('active');
How would I do the same in react? I can toggle what I want to with setState from within the ToggleButton but separating it out into a prop seems to be an answer, but then I need to have the Toolbar manage the button 'active' states and I'm not sure how to do that. Think the answer is in ReactDOM, super newbie to react so apologize if the answer is overly obvious.
import React from 'react';
import FontAwesome from 'react-fontawesome';
import { ButtonGroup } from 'react-bootstrap';
import { ChromePicker} from 'react-color';
class ToolbarButton extends React.Component
{
state =
{
active: false
}
handleClick = ()=> {
if(this.props.onClick)
{
this.props.onClick();
}
this.setState({ active: !this.state.active});
}
render(){
return <div className={`btn btn-primary${this.state.active ? ' active' : ''}`} onClick={this.handleClick}>{this.props.children}</div>
}
}
class ColorPickerButton extends React.Component
{
constructor(props)
{
super(props);
this.state = {
displayColorPicker: false,
color: { r: 255, g: 255, b: 255, a:1 }
}
}
state = {
flyout: 'bottom',
displayColorPicker: false,
color: { r: 255, g: 255, b: 255, a:1 }
}
/* This button should have an option to display how the colorpicker flys out */
static flyoutStyles =
{
normal: { },
top: {top: '0px' },
bottom: { top: '100%' },
left: { right: '100%' },
right: { left: '100%' }
}
handleClick = (e) => {
this.setState({ displayColorPicker: !this.state.displayColorPicker});
}
handleClose = () => {
this.setState({ displayColorPicker: false });
}
handleChange = (color) => {
this.setState({ color: color.rgb });
}
stopPropagation = (e) => {
e.stopPropagation();
}
render()
{
const swatchStyle = {
backgroundColor: `rgba(${this.state.color.r},
${this.state.color.g},
${this.state.color.b},
${this.state.color.a})`,
height: '16px',
width: '16px',
border: '1px solid white'
};
const popup = {
position: 'absolute',
zIndex: 2,
top: 'calc(100% + 2px)'
};
const cover = {
position: 'fixed',
top: '0px',
right: '0px',
left: '0px',
bottom: '0px',
};
return (
<ToolbarButton onClick={this.handleClick} active={this.state.displayColorPicker}>
<div style={swatchStyle} />
{
this.state.displayColorPicker ?
<div style={popup} onClick={this.stopPropagation}>
<div style={ cover } onClick={ this.handleClose }/>
<ChromePicker color={this.state.color} onChange={this.handleChange} />
</div>
: null
}
</ToolbarButton>
);
}
}
export class CanvasToolbar extends React.Component
{
handleClick = (e) => {
}
render(){
return (<div className="CanvasToolbar">
<ButtonGroup vertical>
<ToolbarButton>
<FontAwesome name='paint-brush' />
</ToolbarButton>
<ToolbarButton>
<FontAwesome name='eraser' />
</ToolbarButton>
<ToolbarButton>
<FontAwesome name='magic' />
</ToolbarButton>
<ColorPickerButton />
</ButtonGroup>
</div>);
}
}
I am trying React MobX on hover over a list item. Here is my code
export default observer(
class SidebarContent extends React.Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.store.fetchSources()
}
toggleHover(){
this.props.store.hover = !this.props.store.hover;
}
getArticles(src) {
this.props.store.fetchArticles(src);
}
render() {
const style1 = this.props.style ? {...styles.sidebar, ...this.props.style} : styles.sidebar;
const { sources, hover } = this.props.store
var linkStyle;
if (this.props.store.hover) {
linkStyle = {backgroundColor: 'black'}
} else {
linkStyle = {backgroundColor: 'white'}
}
const links = sources.map( (src,index) => (
<a key={index} href='javascript:;' style={styles.sidebarLink} onClick={this.getArticles.bind(this, src.id)} >
<span style={linkStyle} onMouseEnter={this.toggleHover.bind(this)} onMouseLeave={this.toggleHover.bind(this)} >
<img className="ui-avaatar image" src='{ src.urlsToLogos.small }' />
<span className="side-news-item"> {src.name} </span>
</span>
</a>
))
return (
<MaterialTitlePanel title="Menu" style={style1}>
<div style={styles.content}>
<div style={styles.divider} />
{links}
</div>
</MaterialTitlePanel>
);
}
}
);
const styles = {
sidebar: {
width: 256,
height: '100%',
},
sidebarLink: {
display: 'block',
padding: '16px 0px',
color: '#757575',
textDecoration: 'none',
},
divider: {
margin: '8px 0',
height: 1,
backgroundColor: '#757575',
},
content: {
padding: '16px',
height: '100%',
backgroundColor: 'white',
},
};
this.props.store.hover is a observable.
The problem is that when mouse over one item, all of the items get the hover effect. What did I do wrong?
Do not set Component's props directly, set it on upper Component.
or you could use state feature, and always use setState() to change state.
write an subcomponent to control the Button State
code below maybe help
class SidebarContent extends React.Component {
constructor(props) {
super(props);
}
componentWillMount() {
this.props.store.fetchSources()
}
getArticles(src) {
this.props.store.fetchArticles(src);
}
render() {
const links = sources.map( (src,index) => <Button />);
return (
<MaterialTitlePanel title="Menu" style={style1}>
<div style={styles.content}>
<div style={styles.divider} />
{links}
</div>
</MaterialTitlePanel>
);
}
}
class Button extends React.Component {
toggleHover(){
this.setState({
hover: !this.state.hover,
});
}
render() {
const style1 = this.props.style ? {...styles.sidebar, ...this.props.style} : styles.sidebar;
const { sources } = this.props.store
const { hover } = this.state;
var linkStyle;
if (hover) {
linkStyle = {backgroundColor: 'black'}
} else {
linkStyle = {backgroundColor: 'white'}
}
return (
<a key={index} href='javascript:;' style={styles.sidebarLink} onClick={this.getArticles.bind(this, src.id)} >
<span style={linkStyle} onMouseEnter={this.toggleHover.bind(this)} onMouseLeave={this.toggleHover.bind(this)} >
<img className="ui-avaatar image" src='{ src.urlsToLogos.small }' />
<span className="side-news-item"> {src.name} </span>
</span>
</a>
);
}
}
const styles = {
sidebar: {
width: 256,
height: '100%',
},
sidebarLink: {
display: 'block',
padding: '16px 0px',
color: '#757575',
textDecoration: 'none',
},
divider: {
margin: '8px 0',
height: 1,
backgroundColor: '#757575',
},
content: {
padding: '16px',
height: '100%',
backgroundColor: 'white',
},
};
<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>