Why can't I use “this” in a JSX rendered html element?

271
August 08, 2017, at 9:33 PM

My question is about conditionally rendering in JSX & the use of this.

Consider the following code in my React application:

render() {
    return (
        <li onMouseEnter={this.mouseEnter}>
          //things
        </li>
      )
    }

I would like to conditionally render the onMouseEnter attribute so that it doesn't get applied every time the component gets called and displays the <li> tag.

For example:

render() {
    return (
        <li {this.renderMouseEvents()} >
          ...
        </li>
      )
    }

But visual studio complains and says that "[js] "..." expected"

Obviously calling { this.renderMouseEvents() } outside the HTML element accepts the use of this.

Why is this not valid inside an html element in JSX?

What is a proper/cleaner way to accomplish this conditional rendering in JSX?

Any help is appreciated, thanks!

Answer 1

What you have written is not valid JSX syntax. Try the following instead:

mouseEnterBehaviorEnabled() is a function that returns true or false. Here you put your logic for when you want mouseEnter to trigger.

Take a look at the Short circuit evaluation on MDN.

render() {
  return (
    <li onMouseEnter={this.mouseEnterBehaviorEnabled() && this.mouseEnter} >
      ...
    </li>
  );
}

You could of course also just do

render() {
  return (
    <li onMouseEnter={this.mouseEnter} >
      ...
    </li>
  );
}

and run your logic inside mouseEnter before the rest of the original behavior. If those conditions fail, just return false and the rest won't get executed.

Answer 2

Just insert your conditional into the attribute:

import noop from 'lodash/noop';
render() {
    return (
        <li onMouseEnter={ifSatisfies ? this.mouseEnter : noop}>
          //things
        </li>
      )
    }
Answer 3

You can do it by using the spread operator (ES6), and logical AND short circuit evaluation:

...{ onClick: condition && this.handleClick }

Example:

const arr = ["1", "2", "3"]; 
 
class App extends React.Component { 
  constructor(props) { 
    super(props); 
  } 
 
  handleClick = e => { 
    console.log(e.target.innerHTML); 
  }; 
 
  render() { 
    return ( 
      <div> 
        {arr.map(o => { 
          const myProps = { 
            ...{ onClick: o != "1" && this.handleClick } 
          }; 
          return ( 
            <li {...myProps}> 
              {o} 
            </li> 
          ); 
        })} 
      </div> 
    ); 
  } 
} 
 
ReactDOM.render(<App />, document.getElementById("root"));
<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="root"></div>

Answer 4

You can use this in JSX, I don't think this is the problem.

If this is the problem, it may be inside your method renderMouseEvents, did you bind it to this?

But I think it does not work because of what your method renderMouseEvents is returning. Though, it is possible to inject properties, check this out, it may help:

Dynamic attribute in ReactJS

Answer 5

If I understand what you're asking, I believe the problem you are running into has to deal with how JSX transforms into JavaScript.

<el arg1="1" arg2="2">3</el>

is translated to something similar to the following:

React.createElement('el', { arg1: '1', arg2: '2' }, '3');

What you have written is likely attempted to be translated like this, assuming your renderMouseEvents() returns { onMouseEnter: this.mouseEnter }:

React.createElement('li', { { onMouseEnter: this.mouseEnter } }, '...');

This is invalid JavaScript. The compiler is telling you it is expecting ... (JavaScript spread syntax), which will likely resolve this issue.

As noppa mentioned, there may be better ways to achieve what you want. Can you be more specific about the problem you are facing?

Rent Charter Buses Company
READ ALSO
&ldquo;Error: SecurityError: The operation is insecure&rdquo; in Firefox Extension- html2canvas.js

“Error: SecurityError: The operation is insecure” in Firefox Extension- html2canvas.js

I am writing an extension for Firefox that executes a JS on a page loadThe code uses- HTML2Canvas

1145
Specific casing in pretty url - eg domain.com/kanris should display as domain.com/Kanris

Specific casing in pretty url - eg domain.com/kanris should display as domain.com/Kanris

In a business networking site, I have implemented pretty urls to display profiles using htaccess and jsHowever the case in url is shown as typed by the users

232
Alternative for -webkit-scrollbar [duplicate]

Alternative for -webkit-scrollbar [duplicate]

This question already has an answer here:

404
boostrap-file upload ImagePreview as well as newly added photos

boostrap-file upload ImagePreview as well as newly added photos

If lets say I have Image 1 and 2 from the Ajax call and displayed as the preview, then I want to add another image as Image 3, How do I include the Image 1 and 2 into my array when I send the array to the ajax? Like:

257