1

I am using React JSX. I have a div with className="shadow" as shown below.

<div className="main">
  <div className="shadow" style={{backgroundColor: "#FFFFFF"}}>
    <div id="wrapper">
      Hello
    </div>
  </div>
</div>

Based on a certain condition being true or false, I want to remove the div with className="shadow", but want to keep every div including the div with id="wrapper" intact. Something like unwrap() method of jQuery. Something to the effect of what is written below, but without so many lines of code.

  if ( currentPage==="login") {
   <div className="main">
     <div id="wrapper">
       Hello
     </div>
   </div>
}
else {
    <div className="main">
  <div className="shadow" style={{backgroundColor: "#FFFFFF"}}>
    <div id="wrapper">
      Hello
    </div>
  </div>
</div>
}

I checked React.js: Wrapping one component into another and How to pass in a react component into another react component to transclude the first component's content?, but didn't get what I am looking for.

Community
  • 1
  • 1
abhi
  • 349
  • 2
  • 8
  • 24

2 Answers2

0

Maybe what can help you is to change the className based on the page you are on, because what you try to do would be better using react-router to display different components based on the path you are on.

Use something similar to this code, I hope I can help you.

const App = React.createClass({
  changePage(nextPage) {
    this.setState({ page: nextPage })
  },
  getInitialState() {
    return({
      page: 'Login'
    })
  },
  render() {
    return(
      <div className="main">
        <div className={ this.state.page === 'Login' ? 'shadow' : '' }>
          <div id="wrapper">
            Hello from { this.state.page } page.
          </div>
          <button onClick={ this.changePage.bind(null, 'Login') }>Go to Login page.</button>
          <button onClick={ this.changePage.bind(null, 'Home') }>Go to Home page.</button>
        </div>
      </div>
    )
  }
})

ReactDOM.render(<App />, document.getElementById('app'))
div.shadow{ background-color: #000000; 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>
<div id='app'></div>
Rui Costa
  • 800
  • 4
  • 13
  • 1
    I guess this method won't let me remove the div with class "shadow" from the dom when current page is not login. It will just add/remove the class "shadow" from that div. – abhi Mar 31 '17 at 03:02
0

This is a great use case for Higher Order Components!

const HOC = (currentPage, Shadow, Wrapper) => (
  () => <div className="main">
    {
      currentPage === 'login'
        ? <Shadow {...this.props} />
        : <Shadow {...this.props}><Wrapper {...this.props}>{this.props.children}</Wrapper></Shadow>
    }
  </div>
)

Usage:

render () {
  const Shadow = props => <div className="shadow" style={{backgroundColor: '#FFFFFF'}}>{props.children}</div>
  const Wrapper = props => <div id="wrapper">Hello</div>

  const Example = HOC(
    currentPage,
    Shadow,
    Wrapper
  )

  return (
    <Example />
  )
}

Update:

To render the children of <Wrapper />, use {this.props.children} and use the class syntax in HOC:

const HOC = (currentPage, Shadow, Wrapper) => (
  class extends Component {
    render () {
      return (
        <div className="main">
          {
            currentPage === 'login'
              ? <Shadow />
              : <Shadow><Wrapper>{this.props.children}</Wrapper></Shadow>
          }
        </div>
      )
    }
  }
)

If you needed to capture props on <Shadow /> and <Wrapper />, then do something like the following. Note: I don't think you can pass props into normal DOM elements like <div> tags. But if they were other components with a Capital starting letter, then I believe passing props through with {...this.props} would work nicely.

const HOC = (currentPage, Shadow, Wrapper) => (
  class extends Component {
    render () {
      return (
        <div className="main">
          {
            currentPage === 'login'
              ? <Shadow {...this.props} />
              : <Shadow {...this.props}><Wrapper {...this.props}>{this.props.children}</Wrapper></Shadow>
          }
        </div>
      )
    }
  }
)
Raphael Rafatpanah
  • 19,082
  • 25
  • 92
  • 158
  • This solution seemed to work for me. But, unfortunately instead of "Hello" inside div with id "wrapper", I have . This Content component returns different components based on "currentPage". So, somewhere it is getting lost in an infinite loop and never rendering the desired result. Only is fine, but Content with currentPage as its props is causing problems, but even I am not sure why that is happening. – abhi Mar 31 '17 at 04:50
  • @abhi, Updated. You can render ``'s children with `{this.props.children}`. Let me know if you have any trouble. – Raphael Rafatpanah Mar 31 '17 at 11:30
  • it is still behaving the same way, never rendering the content on the page. So, I decided to go the traditional way using if else conditional rendering. – abhi Apr 02 '17 at 02:01
  • @abhi, I have tested the code in my answer and know that it works. Please verify that you are 1) using the class syntax as outlined in my previous update and 2) are using `{this.props.children}` in your `render ()` method. – Raphael Rafatpanah Apr 02 '17 at 02:04
  • Yes I am using class syntax as well as {this.props.children} in my render method. I can't post my complete code here, but I guess somewhere in my long complicated code, it gets lost and fails to render. – abhi Apr 03 '17 at 02:49