hide a div in react when there is no anchor tag in it

Viewed 234

I have a react code (just a snippet, its not a complete code) as shown below which shows the list of programs on the webpage. Line A in the react code below renders all list of program on the webpage.

react code:

const renderPrograms = () => {
    return programs.map((program, index)=>{
        return (
            <a href={program.url} key={index}>
                <div className="program" >
                    <div class="hello-world">{program.name}</div>
                </div >
            </a>
        )
    })
}


return(
<div class="parent-div">
    <div className ="pqr-xyz">  
        <h5>Hello World</h5>            
    </div>
    <div className ="abc-def">  
        <h5>Programs</h5>
        {programs && renderPrograms()}   {/*Line A*/}
    </div>
</div> 
)

The above react code renders the following html code at runtime:

<div class="parent-div">
    <div className ="pqr-xyz">  
        <h5>Hello World</h5>            
    </div>
    <div class="abc-def">
       <h5>Programs</h5>
       <a href="https://www.google.com/">
            <div class="program">  
              <div class="hello-world">TYUV</div>
            </div>
       </a>
       <a href="https://www.twitter.com/">
            <div class="program"> 
              <div class="hello-world">SGHS</div>
            </div>  
       </a>
    </div>
</div>

Problem Statement:

When Line A does not render anything, my div (<div className ="abc-def">) will look like this at run time:

<div class="abc-def">   
  <h5>Programs</h5>
</div>

I am wondering what changes I need to make in my react code above so that when Line A doesn't render anything then <div class="abc-def"><h5>Programs</h5></div> should not display on the webpage.

7 Answers

They should be part of the condition:

return(
    programs.length > 0 && <div className ="abc-def">  
        <h5>Programs</h5>
        {renderPrograms()} 
    </div>
)

I changed the condition to check for length, otherwise you'll get a 0 instead of nothing, when empty

Try change this lines:

    <div className ="abc-def">  
        <h5>Programs</h5>
        {programs && renderPrograms()}   {/*Line A*/}
    </div>

into this:

    { programs && ( 
        <div className ="abc-def">  
            <h5>Programs</h5>
            {renderPrograms()}   {/*Line A*/}
        </div>
    ) }

Now without programs nothing is displayed.

You can try adding a className like this:

<div className={`abc-def ${programs.length ? "hidden" : ""}`}

Or from the parent componet, you can choose to not render this component with <div>

Instead of trying to hide it using CSS, you also can choose to not render it at all by returning nothing from your function

const RenderPrograms = ({ programs = [] }) => {

  if (!programs.length) {
    return []
  }

  return (
    <div className="abc-def">
      <h5>Programs</h5>
      {programs.map((program, index) =>
        <a href={program.url} key={index}>
          <div className="program">
            <div>{program.name}</div>
          </div>
        </a>
      )}
    </div>
  )
}

ReactDOM.render(
  <RenderPrograms />,
  document.getElementById('react')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

You can try putting your class in a template string and using a ternary operator to display a certain class when some state value is true.

          <div className={`${stateValue ? "name-of-class-with-hide" : "abc-def"}`}>

Here is a complete solution. All you need to do is move the <h5>Programs</h5> inside the condition and modify the condition slightly as shown in following snippet.

    <div className ="abc-def">  
        {
            programs.length > 0 && (
               <div>
                 <h5>Programs</h5>
                 <RenderPrograms programs = {programs}/>
               </div>
            )
        }
    </div>

Note that I have modified the RenderPrograms function as well to accept arguments.

Following is a full snippet.

function RenderPrograms(props) {
    return props.programs.map((program, index)=>{
        return (
            <a href={program.url} key={index}>
                <div className="program" >
                    <div className="hello-world">{program.name}</div>
                </div >
            </a>
        )
    });
}

function MyApp() {
  const programs=[
                      {name:'program 1', url: 'https://url1.com'},
                      {name:'program 2', url: 'url2'},
                      {name:'program 3', url: 'url3'},
                    ];
  const programs1 = []; // empty program list
  return(
    <div class="parent-div">
        
        <h1>When programs list is not empty</h1>
        {/*Above line is just for explanation -- you may remove it*/}
        <div className ="pqr-xyz">  
            <h5>Hello World</h5>            
        </div>
        <div className ="abc-def">  
            {
                programs.length > 0 && (
                   <div>
                     <h5>Programs</h5>
                     <RenderPrograms programs = {programs}/>
                   </div>
                )
            }
        </div>
        
        {/*Below code is just for explanation -- you may remove it*/}
        <hr />
        <h1>When programs list is empty</h1>
        
        <div className ="pqr-xyz">  
            <h5>Hello World</h5>            
        </div>
        <div className ="abc-def">  
            {
                programs1.length > 0 && (
                   <div>
                     <h5>Programs</h5>
                     <RenderPrograms programs = {programs1}/>
                   </div>
                )
            }
        </div>
        
    </div> 
  )
}

ReactDOM.render(
  <MyApp />,
  document.getElementById('app')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

You need to move rendering of programs into RenderPrograms component. Make RenderPrograms component purelu functional and pass data to it via props (Instead of using function).

 const RenderPrograms = ({ programs }) => {
  let disp = programs.map((program, index) => {
    return (
      <a href={program.url} key={index}>
        <div className="program">
          <div class="hello-world">{program.name}</div>
        </div>
      </a>
    );
  });

  return disp || <span />;
};

then use RenderPrograms to render programs in main component (One with logis for loading programs).

     // let programs = [
  //   {
  //     url: "test1.com",
  //     name: "test1"
  //   },
  //   {
  //     url: "test2.com",
  //     name: "test2"
  //   }
  // ];

  let programs = [];

  return (
    <div className="App">
      <div class="parent-div">
        <div className="pqr-xyz">
          <h5>Hello World</h5>
        </div>
        <div className="abc-def">
          <h5>Programs</h5>

          <RenderPrograms programs={programs} />
          {/* {programs && renderPrograms()} Line A */}
        </div>
      </div>
    </div>
  );

You can play around with this sandbox

Related