Passing button click from child to parent in React - reactjs

While trying to toggle between two child components, I need to have the trigger button in the child component, and pass the click function through the child component to the in order to toggle the other child component. I'm not sure how to push the props from the child to the parent in order to trigger the toggle.
Parent component
import React from 'react'
import CancelOffer from '../CancelPages/CancelOffer'
import CancelWarning from '../CancelPages/CancelWarning'
class Cancel extends React.Component {
constructor() {
super()
this.state = {
isHidden: true
}
}
toggleOffer() {
this.setState({
isHidden: !this.state.isHidden
})
}
render() {
return (
<div className = 'cancel'
style = {{backgroundImage: `url(${this.props.backgroundImage})`}} >
<div className = 'container' >
{!this.state.isHidden &&
<CancelOffer { ...this.props}/>
}
{this.state.isHidden &&
<CancelWarning { ...this.props}/>
}
{this.state.isHidden &&
<button onClick = {this.toggleOffer.bind(this)} > Click < /button>
}
</div>
</div>
)
}
}
export default Cancel
Child component
import React from 'react'
import SvgIcon from '../SvgIcon/SvgIcon'
import './CancelWarning.scss'
function CancelOffer (props) {
const content = props.config.contentStrings
return (
<div className='cancel-warning'>
<h2 className='heading md'>heading</h2>
<p className='subpara'>subheading</p>
<div className='losses'>
<ul>
<li>text</li>
<li>text</li>
<li>text</li>
</ul>
</div>
<div className='footer-links'>
<a href='/member' className='btn btn--primary btn--lg'>continue</a>
<a href='/cancel' className='cancel-link'>Cancel</a>
//NEED TO HAVE BUTTON HERE AND PASS PROPS TO PARENT TO TOGGLE VIEW
{this.state.isHidden &&
<button onClick = {this.toggleOffer.bind(this)}>Click</button>
}
</div>
</div>
)
}
export default CancelOffer

You can just pass it like regular param. Also, you can use arrow functions instead of binding.
Parent component
import React from 'react'
import CancelOffer from '../CancelPages/CancelOffer'
import CancelWarning from '../CancelPages/CancelWarning'
class Cancel extends React.Component {
constructor() {
super()
this.state = {
isHidden: true
}
this.toggleOffer = this.toggleOffer.bind(this);
}
toggleOffer() {
this.setState({
isHidden: !this.state.isHidden
})
}
render() {
const { isHidden } = this.state
return (
<div className = 'cancel'
style = {{backgroundImage: `url(${this.props.backgroundImage})`}} >
<div className = 'container' >
{!isHidden &&
<CancelOffer toggleOffer={this.toggleOffer} isHidden={isHidden}/>
}
{isHidden &&
<CancelWarning toggleOffer={this.toggleOffer} isHidden={isHidden}/>
}
{isHidden &&
<button onClick = {this.toggleOffer}> Click </button>
}
</div>
</div>
)
}
}
export default Cancel
Child component
import React from 'react'
import SvgIcon from '../SvgIcon/SvgIcon'
import './CancelWarning.scss'
function CancelOffer (props) {
const content = props.config.contentStrings
return (
<div className='cancel-warning'>
<h2 className='heading md'>heading</h2>
<p className='subpara'>subheading</p>
<div className='losses'>
<ul>
<li>text</li>
<li>text</li>
<li>text</li>
</ul>
</div>
<div className='footer-links'>
<a href='/member' className='btn btn--primary btn--lg'>continue</a>
<a href='/cancel' className='cancel-link'>Cancel</a>
{props.isHidden &&
<button onClick = {props.toggleOffer}>Click</button>
}
</div>
</div>
)
}
export default CancelOffer

Related

How to set state properly in react js

I have 2 react components -
import React, {Component} from 'react'
import './App.css';
import ContactCard from './components/ContactCard'
class App extends Component {
render() {
return (
<div className="App-header">
<ContactCard name="hi 1" age={36} email="hu#yahoo.com"/>
<ContactCard name="hi 2" age={67} email="hi#yahoo.com"/>
<ContactCard name="hi 2" age={42} email="he#yahoo.com"/>
</div>
);
}
}
export default App;
import React, { Component } from "react";
class ContactCard extends Component {
state = {
showAge: false,
};
setAge = () => {
this.setState({
showAge: !this.state.showAge,
});
};
render() {
return (
<div className="contactCard">
<div className="userDetails">
<h2>Name: {this.props.name}</h2>
<p>Email: {this.props.email}</p>
<button onClick={this.state.setAge}>Show Age</button>
{this.state.showAge && <p>Age: {this.props.age}</p>}
</div>
</div>
);
}
}
export default ContactCard;
Toggle button is not working. i have set the state before render method. its not mandatory to set the state in the constructor.
Now the error is gone but still toggle button not working.
Whats going wrong?
You are setting state the wrong way. It should be:
setAge = () => {
this.setState({
showAge: !this.state.showAge
});
};
Edit
In order to make your app work as expected, you also have to set the click handler properly:
<button onClick={this.setAge}>Show Age</button>
You have to update your code its this.setAge not this.state.setAge
render() {
return (
<div className="contactCard">
<div className="userDetails">
<h2>Name: {this.props.name}</h2>
<p>Email: {this.props.email}</p>
<button onClick={this.setAge}>Show Age</button>
{this.state.showAge && <p>Age: {this.props.age}</p>}
</div>
</div>
);
}

Using props and other attributes with react component definition

I have created a react component and I'm reusing it in other components.
<SC_Button label = "English" btnStyle = "sc-btn-default--sinhala mb-2" onClick={this.handleClick}/>
But function defined at onClick does not execute because it's with props passed to the component. I guess react reads onClick as a prop as well. I'm quite new to react.
Below way works. But I don't want to wrap my react component with an extra div due to a styling issue.
<div onClick={this.handleClick} >
<SC_Button label = "English" btnStyle = "sc-btn-default--sinhala mb-2"/>
</div>
Is there any way to use props along with other attributes in react component definitions ?
Edit :
Parent Component
import React from 'react';
import { withRouter } from "react-router-dom";
import SC_Button from '../components/button';
class Home extends React.Component {
handleClick = () => {
this.props.history.push('/page2');
}
render() {
return (
<div className="container-fluid">
<div className="row sc-overlay sc-overlay-main">
<div className="col-md-12 col-xl-5 offset-xl-1">
<span className = "sc-overlay-main__left">
<span className = "sc-main-image">
<img src={require('../assets/dialog_logo.png')} />
</span>
<h1 className="mt-4">Welcome to MyDialog</h1>
</span>
</div>
<div className="col-md-12 col-xl-5">
<div className="row sc-overlay-main__right">
<label>Choose your preferred language</label>
<SC_Button label = "සිංහල" btnStyle = "sc-btn-default--sinhala mb-2" onClick={this.handleClick}/>
<SC_Button label = "தமிழ்" btnStyle = "sc-btn-default--tamil mb-2" />
<SC_Button label = "English" btnStyle = "sc-btn-default--english mb-2" />
</div>
</div>
</div>
</div>
);
}
}
export default withRouter(Home);
SC_Button Component
import React from 'react';
import { withRouter } from "react-router-dom";
class SC_Button extends React.Component{
constructor(props) {
super(props);
}
render() {
return (
<button type="button" className={`sc-btn-default ${ this.props.btnStyle }`}>{this.props.label}</button>
);
}
}
export default withRouter(SC_Button);
Your <SC_Button /> component, or any custom component you make, doesn't automatically implement an event handler. You're essentially just giving it yet another prop, called onClick, that it just throws away. You have to use the callback you're passing it in the DOM elements it returns:
SC_Button.js
import React from 'react';
import { withRouter } from "react-router-dom";
class SC_Button extends React.Component{
constructor(props) {
super(props);
}
render() {
return (
<button
type="button"
className={`sc-btn-default ${ this.props.btnStyle }`}
onClick={this.props.handleClick}
>
{this.props.label}
</button>
);
}
}
export default withRouter(SC_Button);
There is no need to define a handleClick function in the component, since you will be passing it as a prop every time you instantiate one. This allows different instances to have different behaviors.

How to retrieve state from a component

I have a Modal dialog component that takes another component as content and returns a promise for handling the result (Idea is from here). How can I extract the 'time' state from the content in order to add it to the promise chain?
import React from 'react'
import Modal from './Modal'
class Late extends React.Component {
constructor(props) {
super(props);
this.state = {
time: '18:48'
};
}
render() {
return (
<div className='modal-body'>
{this.time}
</div>
);
}
}
export default function(message, options) {
var form = <Late description={options.description} />;
return Modal(form, message, options).then(() => ??);
}
import React from 'react'
import ReactDOM from 'react-dom'
import '../css/modal.css'
import Promise from 'bluebird'
import _ from 'lodash'
Promise.config({ cancellation: true });
class Modal extends React.Component {
constructor(props) {
super(props);
this.resolve = null;
}
abort = () => this.promise.cancel();
confirm = () => this.resolve();
componentDidMount() {
this.promise = new Promise(resolve => this.resolve = resolve);
return ReactDOM.findDOMNode(this.refs.confirm).focus();
}
backdrop = () => <div className='modal-backdrop in' />;
modal() {
var style = {display: 'block'};
return (
<div
className='modal in'
tabIndex='-1'
role='dialog'
aria-hidden='false'
ref='modal'
style={style}
>
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
<h4 className='modal-title'>
{this.props.message}
</h4>
</div>
{this.props.children}
<div className='modal-footer'>
<div className='text-right'>
<button type='button' className='btn btn-default' onClick={this.abort} >
{this.props.abortLabel}
</button>
{' '}
<button type='button' className='btn btn-primary' ref='confirm' onClick={this.confirm} >
{this.props.confirmLabel}
</button>
</div>
</div>
</div>
</div>
</div>);
}
render() {
return (
<div>
{this.backdrop()}
{this.modal()}
</div>
);
}
}
export default function(content, message, options) {
var cleanup, component, props, wrapper;
if (options == null) {
options = {};
}
props = _.assign({
message: message
}, options);
wrapper = document.body.appendChild(document.createElement('div'));
component = ReactDOM.render(<Modal {...props}>{content}</Modal>, wrapper);
cleanup = function() {
ReactDOM.unmountComponentAtNode(wrapper);
return setTimeout(function() {
return wrapper.remove();
});
};
return component.promise.finally(cleanup);
};
if i understood you correctly, you wish to make some action once the Modal is done(pressed OK i.e). If so ,than you could wrap the Modal with a component and pass a function as a prop to the Modal so that once the Modal component is handling the wished action it can omit the function from prop.
take a look how to pass a function as a prop, and Lift up the state

React - how to pass state to another component

I'm trying to figure out how to notify another component about a state change. Let's say I have 3 components - App.jsx,Header.jsx,and SidebarPush.jsx and all I'm simply trying to do is toggle a class with an onClick.
So the Header.jsx file will have 2 buttons when clicked will toggle the states to true or false. The other 2 components App.jsx and Header.jsx will need to know about these state changes so they can toggle a class
whenever those states change.
App.jsx
import React from 'react';
import Header from 'Header';
import classNames from "classnames";
import SidebarPush from 'SidebarPush';
import PageWrapper from 'PageWrapper';
var MainWrapper = React.createClass({
render: function() {
return (
<div className={classNames({ 'wrapper': false, 'SidebarPush-collapsed': !this.state.sidbarPushCollapsed })}>
<Header/>
<SidebarPush/>
<PageWrapper>
{this.props.children}
</PageWrapper>
</div>
);
}
});
module.exports = MainWrapper;
Header.jsx
import React from 'react';
import ReactDom from 'react-dom';
class Header extends React.Component {
constructor() {
super();
this.state = {
sidbarPushCollapsed: false,
profileCollapsed: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
sidbarPushCollapsed: !this.state.sidbarPushCollapsed,
profileCollapsed: !this.state.profileCollapsed
});
}
render() {
return (
<header id="header">
<ul>
<li>
<button type="button" id="sidbarPush" onClick={this.handleClick} profile={this.state.profileCollapsed}>
<i className="fa fa-bars"></i>
</button>
</li>
<li>
<button type="button" id="profile" onClick={this.handleClick}>
<i className="icon-user"></i>
</button>
</li>
</ul>
<ul>
<li>
<button id="sidbarOverlay" onClick={this.handleClick}>
<i className="fa fa-indent"></i>
</button>
</li>
</ul>
</header>
);
}
};
module.exports = Header;
SidebarPush.jsx
import React from 'react';
import ReactDom from 'react-dom';
import classNames from "classnames";
class SidebarPush extends React.Component {
render() {
return (
<aside className="sidebarPush">
<div className={classNames({ 'sidebar-profile': true, 'hidden': !this.state.pagesCollapsed })}>
....
</div>
<nav className="sidebarNav">
....
</nav>
</aside>
);
}
}
export default SidebarPush;
Move all of your state and your handleClick function from Header to your MainWrapper component.
Then pass values as props to all components that need to share this functionality.
class MainWrapper extends React.Component {
constructor() {
super();
this.state = {
sidbarPushCollapsed: false,
profileCollapsed: false
};
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState({
sidbarPushCollapsed: !this.state.sidbarPushCollapsed,
profileCollapsed: !this.state.profileCollapsed
});
}
render() {
return (
//...
<Header
handleClick={this.handleClick}
sidbarPushCollapsed={this.state.sidbarPushCollapsed}
profileCollapsed={this.state.profileCollapsed} />
);
Then in your Header's render() method, you'd use this.props:
<button type="button" id="sidbarPush" onClick={this.props.handleClick} profile={this.props.profileCollapsed}>

ReactJS Dialog with close button

I want to add close button to my react pop up so I added this line
<button onClick = {$('.scoreboard-trigger').close}>Close</button>
but when I clik Close button it does not close
here is my all component
import $ from 'jquery';
import React from 'react';
import { FormattedMessage } from 'util/IntlComponents';
import OkeyScoreboard from './OkeyScoreboard';
class OkeyScoreboardDialog extends React.Component {
componentDidMount() {
$('.scoreboard-trigger').leanModal({
opacity: 0
});
}
render() {
const { scoreboard, profiles } = this.props;
const scoreboardTitle = <FormattedMessage message="room_title.scoreboard"/>;
return (<div id='scoreboardModal'
className='scoreboard-modal modal'>
<div className='modal-content'>
<h4 className='center'>{scoreboardTitle}</h4>
<OkeyScoreboard profiles={profiles} scoreboard={scoreboard}/>
<button onClick = {$('.scoreboard-trigger').close}>Close</button>
</div>
<div className='modal-footer'>
</div>
</div>);
}
}
class OkeyScoreboardDialogTrigger extends React.Component {
render() {
const scoreboardTitle = <FormattedMessage message="room_title.scoreboard"/>;
return <a className='scoreboard-trigger modal-trigger btn blue-grey darken-3'
href='#scoreboardModal'>
{scoreboardTitle}
</a>;
}
}
export { OkeyScoreboardDialog };
export { OkeyScoreboardDialogTrigger };
I think you should wrap this in function
$('.scoreboard-trigger').close
in function and pass it to onClick method in button,
I create the example wrap it in function close and pass it to the onClick
import $ from 'jquery';
import React from 'react';
import { FormattedMessage } from 'util/IntlComponents';
import OkeyScoreboard from './OkeyScoreboard';
class OkeyScoreboardDialog extends React.Component {
componentDidMount() {
$('.scoreboard-trigger').leanModal({
opacity: 0
});
}
close() {
$('.scoreboard-trigger').close;
}
render() {
const { scoreboard, profiles } = this.props;
const scoreboardTitle = <FormattedMessage message="room_title.scoreboard"/>;
return (<div id='scoreboardModal'
className='scoreboard-modal modal'>
<div className='modal-content'>
<h4 className='center'>{scoreboardTitle}</h4>
<OkeyScoreboard profiles={profiles} scoreboard={scoreboard}/>
<button onClick = {this.close()}>Close</button>
</div>
<div className='modal-footer'>
</div>
</div>);
}
}
class OkeyScoreboardDialogTrigger extends React.Component {
render() {
const scoreboardTitle = <FormattedMessage message="room_title.scoreboard"/>;
return <a className='scoreboard-trigger modal-trigger btn blue-grey darken-3'
href='#scoreboardModal'>
{scoreboardTitle}
</a>;
}
}
export { OkeyScoreboardDialog };
export { OkeyScoreboardDialogTrigger };here
Try to use reacjs-popup A simple react popup component ( 3kb)

Resources