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.
Related
onmouse is not working when I hover my mouse on the text in h1 tag, but its printing value in the console when I click on it.
import React, {
Component
} from 'react';
class App extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick = (event) => {
let word = event.target.innerText;
console.log(word)
}
render() {
return (<div>
<div className="App">
<h1 onMouseOver = {this.handleClick}>hover Me</h1>
</div>
</div>);
}
}
export default App;
the code works fine, only the "super(props)" part has been deprecated, another trick: when you use Arrow functions you don't need to bind the function in the constructor. This is the complete code:
import React, { Component } from 'react';
class YourComponent extends Component {
constructor(props) {
super();
this.state={};
}
handleClick = (event) => {
let word = event.target.innerText;
console.log(word)
}
render() {
return (
<div>
<div className="App">
<h1 onMouseOver={this.handleClick}> hover Me </h1>
</div>
</div>
);
}
}
export default YourComponent;
Enjoy ;)
I want to make when i click button, show modal in different class.
how to make it this?
import React, { Component } from 'react';
import addmodal from './addmodal';
class page extends Component {
...//skip
handleAdd= () =>{
//...how?
}
render(){
return (
<button onClick={this.handleAdd} > Add </button>
)
}
}
import React, { Component } from 'react';
class addmodal extends Component {
// ... skip
render(){
return(
<modal inOpen={this.state.isopen} >
...//skip
</modal>
)
}
}
export default addmodal;
I can't call this addmodal...
how to call modal?
First, your variable naming is terrible. I fixed it for you here. The state that dictates if modal is open must be on the parent component since you have your trigger there. Then, pass it as props to the modal component. Here is the fixed code for you:
import React, { Component } from 'react';
import AddModal from './addmodal';
class Page extends Component {
constructor(){
super();
this.state = { isModalOpen: false };
}
...//skip
handleAdd= () =>{
this.setState({ isModalOpen: true });
}
render(){
return (
<div>
<button onClick={this.handleAdd} > Add </button>
<AddModal isOpen={this.state.isModalOpen} />
</div>
)
}
}
import React, { Component } from 'react';
class AddModal extends Component {
// ... skip
render(){
return(
<modal inOpen={this.props.isOpen} >
...//skip
</modal>
)
}
}
export default AddModal;
what about using trigger. Its very usefull.
<Modal trigger={ <button onClick={() => onCLickPay()} className={someting}> When clicked here modal with show up</button> }`enter code here` >
Can I use children in React Container or is it wrong?
For example, I have a list of buttons(ActionButton) that are grouped together (ActionMenu).
import React from 'react';
class App extends React.Component {
render() {
return (
<ActionMenu>
<ActionButton name="New" icon="add" />
<ActionButton name="Delete" icon="remove" />
</ActionMenu>
)
}
}
class ActionMenu extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
alert('Click!');
}
render() {
return React.Children.map(this.props.children, (button) =>
React.cloneElement(button, {
onClick: this.handleClick
})
);
}
}
function ActionButton({ name, icon, onClick }) {
return <button class={icon} onClick={onClick}>{name}</button>
}
You can use children regardless of whether it's a component of container.
"[children are] especially common for components like Sidebar or Dialog that represent generic 'boxes'."
In your case you have a menu, which falls into this category.
https://reactjs.org/docs/composition-vs-inheritance.html
I think this is what you are after. Actually you should just put the children in its closest parent instead of its grandpa.
import React from 'react';
import { render } from 'react-dom';
function ActionButton({ name, handleClick }) {
return <button onClick={handleClick}>{name}</button>
}
class ActionMenu extends React.Component {
constructor(props) {
super(props);
}
handleClick = () => {
alert('Click!');
}
render() {
return (
<div>
<ActionButton name="add" handleClick={this.handleClick}/>
<ActionButton name="remove" handleClick={this.handleClick} />
</div>
);
}
}
class App extends React.Component {
render() {
return (
<ActionMenu />
)
}
}
render(<App />, document.getElementById('root'));
You can try to run it in sandbox.
By the way, using bind is quite redundant now, we can use public class fields syntax, which is already ECMA stage 2.
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>
);
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)