2

I am making a pen where when user clicks on hamburger icon (top left), I want it to open the sidebar. I saw a thread on SO explaining how to do it here.

In short, the solution is to do something like this:

isActive:function(value){
    return 'btn '+((value===this.state.selected) ?'active':'default');
  },

I am trying to do something similar (a little different); here is what I did:

expandSidebar(){
    this.setState({active: !this.state.active});
    console.log(this.state.active ? "square-left active" : "square-left");
    return this.state.active ? "square-left active" : "square-left"
  }
...

//different React component
<div className={this.props.expandSidebar}>
...

But it does not work. My goal is to display the sidebar when it is clicked, by adding active class. When I console log it, it returns the right string, "square-left active".

This is the codepen: https://codepen.io/iggPen/pen/BdEJmw

What did I do wrong? I am pretty sure it is returning square-left active, but it is not displaying sidebar.

2
  • In your pen change <SidebarRectangle expandSidebar={this.expandSidebar} /> to <SidebarRectangle expandSidebar={this.expandSidebar()} /> Commented Sep 5, 2017 at 20:49
  • Hi Prakash, it didn't work. When I do <SidebarRectangle expandSidebar={this.expandSidebar()} />, everything disappeared. Commented Sep 5, 2017 at 21:16

2 Answers 2

3

You can't pass a function as className.
You should pass a prop of active and do the className logic inside the SidebarRectangle component.
For example (i've added an active prop to this component):
this.props.active ? "square-left active" : "square-left"

Modified version of your code:

const sidebarOptions = ["Sidebars", "Are", "Super", "Cool"]

class SidebarRectangle extends React.Component {
  constructor(){
    super();
  }
  render(){
    return (
      <div className={this.props.active ? "square-left active" : "square-left"}>
        {sidebarOptions.map((option, index) => {
          return (
            <div onClick={this.props.expandSidebar} key={index} className="sidebar-element">{option}</div>
            )
        })}
      </div>
    )
  }
}
class MainRectangle extends React.Component {
  constructor(){
    super();
    this.state = {
      active: false
    };
    this.expandSidebar = this.expandSidebar.bind(this);
  }
  expandSidebar(){
    this.setState({active: !this.state.active});
    console.log(this.state.active ? "square-left active" : "square-left");
    return this.state.active ? "square-left active" : "square-left"
  }
  render(){
    return (
    <div className="center">
      <SidebarRectangle expandSidebar={this.expandSidebar} active={this.state.active} />
      <div className="square-main">
        <div className="square-header">
          <span onClick={this.expandSidebar} className="header-notification clickable"><i className="fa fa-bars" aria-hidden="true"></i></span>
          <span className="header-notification">Notifications</span>
          <span></span>
        </div>
      </div>
    </div>
    )
  }
}
class Application extends React.Component {
  render() {
    return(
      <div>
        <MainRectangle />
      </div>
      )
  }
}

ReactDOM.render(<Application />, document.getElementById('app'));
body {
  background: #4FB5FB;
  font-family: "Arial";
}

.center {
  position: absolute;
  left: 50%;
  top: 50%;
}

.square-main {
  position: absolute;
  height: 300px;
  width: 300px;
  left: 50%;
  top: 50%;
  background: #FFFFFF;
  transform: translate(-50%, -50%);
  display: flex;
}

.square-header {
  height: 100px;
  width: 300px;
  background: #DD0031;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.header-notification {
  color: #FFFFFF;
  font-size: 24px;
}

.clickable {
  cursor: pointer;
}

.square-left {
  width: 130px;
  height: 225px;
  background: #199FFA;
  position: absolute;
  left: -150px;
  top: -110px;
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  align-items: center;
}

.active {
  transform: translate3d(-150px, 0, 0);
}

.sidebar-element {
  color: #FFFFFF;
}
<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>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet">
<div id="app"></div>

Sign up to request clarification or add additional context in comments.

Comments

1

I've cleaned up your code a bit, and attached is a working example:

  • Application can be pure functional component, as it only renders
  • SidebarRectangle could be aswell, as it doesn't have any state
  • Classnames for sidebar should be defined in that component
  • Your constructor for MainRectangle can be simplified
  • You don't need to pass a callback function as rendered sidebar items aren't clickable in your example
  • onClick inside SidebarRectangle is not required, as these aren't buttons in your example that can be clicked.

const sidebarOptions = ["Sidebars", "Are", "Super", "Cool"];

class SidebarRectangle extends React.Component {
  render() {
    const { isActive } = this.props;

    return (
      <div className={`${isActive ? "square-left active" : "square-left"}`}>
        { sidebarOptions.map((option, index) => {
          return (
            <div key={index} className="sidebar-element">{option}</div>
            )
        }) }
      </div>
    )
  }
}

class MainRectangle extends React.Component {
  state = {
    isActive: false
  }

  handleExpandSidebar = () => {
    this.setState({ isActive: !this.state.isActive });
  }

  render(){
    const { isActive } = this.state;

    return (
      <div className="center">
        <SidebarRectangle isActive={isActive} />
        <div className="square-main">
          <div className="square-header">
            <span onClick={this.handleExpandSidebar} className="header-notification clickable"><i className="fa fa-bars" aria-hidden="true" /></span>
            <span className="header-notification">Notifications</span>
            <span></span>
          </div>
        </div>
      </div>
    )
  }
}

const Application = () => {
  return(
    <div>
      <MainRectangle />
    </div>
  )
}

ReactDOM.render(<Application />, document.getElementById('app'));
body {
  background: #4FB5FB;
  font-family: "Arial";
}

.center {
  position: absolute;
  left: 50%;
  top: 50%;
}

.square-main {
  position: absolute;
  height: 300px;
  width: 300px;
  left: 50%;
  top: 50%;
  background: #FFFFFF;
  transform: translate(-50%, -50%);
  display: flex;
}

.square-header {
  height: 100px;
  width: 300px;
  background: #DD0031;
  display: flex;
  justify-content: space-around;
  align-items: center;
}

.header-notification {
  color: #FFFFFF;
  font-size: 24px;
}

.clickable {
  cursor: pointer;
}

.square-left {
  width: 130px;
  height: 225px;
  background: #199FFA;
  position: absolute;
  left: -150px;
  top: -110px;
  display: flex;
  flex-direction: column;
  justify-content: space-evenly;
  align-items: center;
}

.active {
  transform: translate3d(-150px, 0, 0);
}

.sidebar-element {
  color: #FFFFFF;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css" rel="stylesheet"/>
<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>
<div id="app"></div>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.