Reputation: 467
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>
);
}
}
Upvotes: 1
Views: 18092
Reputation: 8158
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.
Upvotes: 4