React how to pass an state to another component - reactjs

Hello i split my app and would like to pass the state from my <button />
to <menu /> I'm simply trying to do is toggle a function with an onClick.
So the Button.js file will have 1 buttons when clicked will toggle the states to visible or invisible. The menu component Menu.js will need know about these state changes so they can toggle the function and will show the menu
Button component
import React, { PureComponent } from 'react';
import CSSTransitionGroup from 'react-addons-css-transition-group';
import { themr } from 'react-css-themr';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import localStyles from './NavButton.scss';
#themr('NavButton', localStyles)
export default class NavButton extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: false,
};
this.toggleMenu = this.toggleMenu.bind(this);
}
toggleMenu() {
this.setState({
visible: !this.state.visible
})
console.log('toggle');
}
render() {
const {theme } = this.props;
return (
<div className={theme['nav-button']} onClick={this.toggleMenu}>
<span></span>
<span></span>
</div>
);
}
}
Menu
import React, { PureComponent } from 'react';
import CSSTransitionGroup from 'react-addons-css-transition-group';
import { themr } from 'react-css-themr';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import localStyles from './Menu.scss';
import { NavButton } from '../../components';
#themr('Menu', localStyles)
export default class Menu extends React.Component {
render() {
return (
<div className="menu-wrapper">
<CSSTransitionGroup
transitionName="menu"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
{this.state.visible &&
<Menus alignment="right">
<MenuItem hash="first-page">First Page</MenuItem>
<MenuItem hash="second-page">Second Page</MenuItem>
<MenuItem hash="third-page">Third Page</MenuItem>
</Menus>}
</CSSTransitionGroup>
</div>
);
}
}
const Menus = ({alignment, children, theme }) => (
<div className="menu">
<div className={alignment}>{children}</div>
</div>
);

Although you have imported Button component to Menu, you are not using it, Also what you should do is keep the state visible in the menu component and communicate to Menu from Button component like
export default class Menu extends React.Component {
constructor(props) {
super(props);
this.state = {
visible: false,
};
this.toggleMenu = this.toggleMenu.bind(this);
}
toggleMenu() {
this.setState({
visible: !this.state.visible
})
console.log('toggle');
}
render() {
return (
<NavButton toggleMenu={this.toggleMenu}/>
<div className="menu-wrapper">
<CSSTransitionGroup
transitionName="menu"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}>
{this.state.visible &&
<Menus alignment="right">
<MenuItem hash="first-page">First Page</MenuItem>
<MenuItem hash="second-page">Second Page</MenuItem>
<MenuItem hash="third-page">Third Page</MenuItem>
</Menus>}
</CSSTransitionGroup>
</div>
);
}
}
const Menus = ({alignment, children, theme }) => (
<div className="menu">
<div className={alignment}>{children}</div>
</div>
);
Now you NavButton will be like
export default class NavButton extends React.Component {
render() {
const {theme } = this.props;
return (
<div className={theme['nav-button']} onClick={this.props.toggleMenu}>
<span></span>
<span></span>
</div>
);
}
}

It's better to maintain the state of an application at the top most component, so it kinda governs the brains of the app.
If you moved the state into the Menu, you can pass the onClick callback into the Button e.g.
Menu.js
<NavButton toggleClick={this.handleClick} />
Then you can move the State information into the Menu as well as the handleClick function.
This allows the Button to be stateless:
const NavButton = ({theme, toggleClick}) => (
<div className={theme['nav-button']} onClick={toggleMenu}>
<span></span>
<span></span>
</div>
);

Related

Trying to change a square's visibility with props

I have a very basic program that is supposed to hide a square when I button is pressed. Within the Game component, it seems to be updating fine whenever I press the button, and sends an alert whenever I press the button with the current visibility. But when I try to update the square's visibility, it doesn't work.
import React from "react"; import ReactDOM from "react-dom"; import "./index.css";
function Square(props) {
return (
<div className="square" style={{ visibility: props.visibility }}></div>
); }
function Button(props) {
return (
<button type="button" onClick={props.onClick}>
Click to hide square!
</button>
); }
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
visibility: "visible",
};
}
handleClick() {
this.setState({
visibility:
this.state.visibility == "visible" ? "hidden" : "visible",
});
alert(this.state.visibility);
}
render() {
return (
<div>
<Button
onClick={() => this.handleClick()}
visibility={this.state.visibility}
/>
<Square />
</div>
);
} }
ReactDOM.render(<Game />, document.getElementById("root"));
because your Square component doesn't add props visibility to control
import React from "react"; import ReactDOM from "react-dom"; import "./index.css";
function Square(props) {
return (
<div className="square" style={{ visibility: props.visibility, background:'red',width:'100px', height:'100px' }}></div>
); }
function Button(props) {
return (
<button type="button" onClick={props.onClick}>
Click to hide square!
</button>
); }
class Game extends React.Component {
constructor(props) {
super(props);
this.state = {
visibility: "visible",
};
}
handleClick() {
this.setState({
visibility:
this.state.visibility == "visible" ? "hidden" : "visible",
});
alert(this.state.visibility);
}
render() {
return (
<div>
<Button
onClick={() => this.handleClick()}
visibility={this.state.visibility}
/>
<Square visibility={this.state.visibility} />
</div>
);
} }
ReactDOM.render(<Game />, document.getElementById("root"));

How can I tried to render forms to this MainScreen.js file when the user click on in the navbar?

The main form page where the login and Sign up form will live give undefined. How can I tried to render forms to this MainScreen.js file when the user click on in the navbar.
MainScreen.js (Where the forms are live)
import React from 'react';
import RegisterBox from '../Forms/Register'
import LoginBox from '../Forms/Login'
// This is the page for form to live on
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoginOpen: true,
isRegisterOpen: false
};
}
render() {
return (
<div>
<div className="root-container">
{this.state.isLoginOpen && <LoginBox/>}
{this.state.isRegisterOpen && <RegisterBox/>}
</div>
</div>
)
}
}
export default App;
Navigation.js (Where the button is clicked but are not being defined anywhere so cannot find the page to take me to the forms.)
import React from 'react';
import { BrowserRouter as Router, Link } from 'react-router-dom';
import Dropdown from "../components//pages/dropdowns/dropdowns";
import hamburger from "../images/menu.svg"
class Navigation extends React.Component {
constructor(props) {
super(props);
this.state = {
isExpanded: false
};
}
handleToggle(e) {
e.preventDefault();
this.setState(prevState => ({
isExpanded: !prevState.isExpanded, // negate the previous expanded state
}));
}
render() {
const { isExpanded } = this.state;
return (
<Router>
<div className="NavbarContainer">
<div className="mobilecontainer LeftNav">
<h2 className="BrandName LeftNav mobileboxmenu inline FarRight">Kommonplaces</h2>
<div className="hamburger inlinev" >
<img
onClick={e => this.handleToggle(e)}
alt="menubtn"
src={hamburger}
/>
</div>
</div>
<ul className={`NavBar collapsed ${isExpanded ? "is-expanded" : ""}`}>
<Dropdown/>
<li className="RightNav"><Link to="/">Host Your Space</Link></li>
<li className="RightNav"><Link to="/">About Us</Link></li>
<li className="RightNav"><Link to="/">Contact Us</Link></li>
<div className="btnflexright">
<button
className={"controller " + (this.state.isLoginOpen
? "selected-controller"
: "")}
onClick={this
.props
.showLoginBox}>
Login
</button>
<button
className={"controller " + (this.state.isRegisterOpen
? "selected-controller"
: "")}
onClick={this
.props
.showRegisterBox}>
Sign up
</button>
</div>
</ul>
</div>
</Router>
);
}
}
export default Navigation;
You need to do a couple things:
add some couple methods to your App component to set the state.
import and render the Navigation component in your App component (so you can pass your methods in as functions. you could use the Context API but it's more complicated...)
pass those methods as functions to your Navigation component (and pass the state in as props if you need them too)
call the methods through the props of your Navigation component
In your App component:
import React from 'react';
import RegisterBox from '../Forms/Register'
import LoginBox from '../Forms/Login'
import Navigation from './Navigation'
// This is the page for form to live on
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isLoginOpen: true,
isRegisterOpen: false
};
}
/*
* 1. add these two methods here to modify the state of `App`
*/
showLoginBox() {
this.setState({ isLoginOpen: true });
}
showRegisterBox() {
this.setState({ isRegisterOpen: true });
}
render() {
return (
<div>
<div className="root-container">
{
/* 2. render the `Navigation` component in `App` */
/* 3. pass your methods in as function props to `Navigation` */
}
<Navigation
isLoginOpen={this.state.isLoginOpen}
isRegisterOpen={this.state.isRegisterOpen}
showLoginBox={this.showLoginBox.bind(this)}
showRegisterBox={this.showRegisterBox.bind(this)}
/>
{this.state.isLoginOpen && <LoginBox/>}
{this.state.isRegisterOpen && <RegisterBox/>}
</div>
</div>
)
}
}
export default App;
Now you can call those methods from your Navigation component...
{ /* 4. call the prop functions in `Navigation` component */ }
<button
className={"controller " + (this.props.isLoginOpen ? "selected-controller" : "")}
onClick={this.props.showLoginBox}>
Login
</button>
<button
className={"controller " + (this.props.isRegisterOpen ? "selected-controller" : "")}
onClick={this.props.showRegisterBox}>
Sign up
</button>

How to set state in React and Material-ui over .js files?

I'm new for React and Material-UI too. I have this App.js file:
import React, {Component} from 'react';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import AppBar from 'material-ui/AppBar';
import IconButton from 'material-ui/IconButton';
import NavigationMenu from 'material-ui/svg-icons/navigation/menu';
import DrawerMenu from './DrawerMenu';
const AppBarIcon = () => (
<AppBar
title="Title"
iconElementLeft={<IconButton onClick={???}>
<NavigationMenu />
</IconButton>}
/>
);
class App extends Component {
render() {
return (
<div className="App">
<MuiThemeProvider>
<div>
<DrawerMenu />
<AppBarIcon />
</div>
</MuiThemeProvider>
</div>
);
}
}
export default App;
...and this is the DrawerMenu.js file:
import React from 'react';
import Drawer from 'material-ui/Drawer';
import MenuItem from 'material-ui/MenuItem';
export default class DrawerSimpleExample extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
}
handleToggle = () => this.setState({open: !this.state.open});
render() {
return (
<div>
<Drawer open={this.state.open}>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
</div>
);
}
}
Is there any way to set the IconButton's onClick value in App.js file to set the DrawerMenu's state open:true ? For example:
<IconButton onClick={ DrawerMenu.setState({open:true}) }>
...or something like this?
You can use props to achieve desired behavior.
Example
const AppBarIcon = (props) => (
<AppBar
title="Title"
iconElementLeft={<IconButton onClick={props.onIconClick}>
<NavigationMenu />
</IconButton>}
/>
);
class App extends Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
}
onIconClick = () => {
this.setState((prevState) => ({ isOpen: !prevState.isOpen }));
}
render() {
return (
<div className="App">
<MuiThemeProvider>
<div>
<DrawerMenu isOpen={this.state.isOpen} />
<AppBarIcon onIconClick={this.onIconClick} />
</div>
</MuiThemeProvider>
</div>
);
}
}
export default class DrawerSimpleExample extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
}
handleToggle = () => this.setState({open: !this.state.open});
render() {
return (
<div>
<Drawer open={this.props.isOpen}>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
</div>
);
}
}

React Toggle Menu

Im trying to build an Toggle right menu from this example : how-to-build-a-sliding-menu-using-react-js"
the problem is React.createClass is deprecated so i have to change the code and it stop working i get the content but cant access the handlers cann anybody tell me which steps should i do to fix this issue! so if i click on my button i get this error:
Uncaught TypeError: Cannot read property 'show' of undefined
ToggleMenu
import React from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import localStyles from './ToggleMenu.scss';
import { themr } from 'react-css-themr';
import { Menu } from '../../components';
import { MenuItem } from '../../components';
#themr('ToggleMenu', localStyles)
export default class ToggleMenu extends React.Component {
showRight() {
this.refs.right.show();
}
constructor(props) {
super(props);
this.showRight = this.showRight.bind(this);
}
render() {
return (
<div>
<button onClick={this.showRight}>Show Right Menu!</button>
<Menu ref={right => this.right = right} alignment="right">
<MenuItem hash="first-page">First Page</MenuItem>
<MenuItem hash="second-page">Second Page</MenuItem>
<MenuItem hash="third-page">Third Page</MenuItem>
</Menu>
</div>
);
}
}
Menu
import React from 'react';
export default class Menu extends React.Component {
constructor() {
super();
this.state = {
visible: false
}
};
show() {
this.setState({visible: true});
document.addEventListener("click", this.hide.bind(this));
}
hide() {
this.setState({visible: false});
document.removeEventListener("click", this.hide.bind(this));
}
render() {
return (
<div className="menu">
<div className={(this.state.visible ? "visible " : "") + this.props.alignment}>{this.props.children}</div>
</div>
);
}
}
MenuItem
import React from 'react';
export default class MenuItem extends React.Component {
navigate(hash) {
window.location.hash = hash;
}
render() {
return (
<div className="menu-item" onClick={this.navigate.bind(this, this.props.hash)}>{this.props.children}</div>
);
}
}
The problem is that you are assigning the reference to this.right, you need to update the showRight method to something like this:
showRight() {
this.right.show();
}
I'd also use an arrow function to avoid binding the function in the constructor.
import React, { PureComponent } from 'react';
export default class ToggleMenu extends PureComponent {
showRight = () => {
this.right.show();
}
render() {
return (
<div>
<button onClick={this.showRight}>Show Right Menu!</button>
<Menu ref={right => this.right = right} alignment="right">
<MenuItem hash="first-page">First Page</MenuItem>
<MenuItem hash="second-page">Second Page</MenuItem>
<MenuItem hash="third-page">Third Page</MenuItem>
</Menu>
</div>
);
}
}
And make sure to use PureComponent to avoid rendering the component when is not needed.
Edit:
The Menu class is not the react way, if you want to hide an element you should do something like the following:
import React from 'react';
export default class Menu extends React.Component {
state = {
visible: false,
};
show() {
this.setState({ visible: true });
}
hide() {
this.setState({ visible: false });
}
render() {
const { visible } = this.state;
return (
<div className="menu">
{
visible &&
<div className={this.props.alignment}>{this.props.children}</div>
}
</div>
);
}
}
If visible === true then the div will render, otherwise it won't. I removed the listeners, we don't do that in react, instead you need to define an onClick callback on the element that you want the user to click in order to hide the menu.

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