Why can't I use "this" in the JSX rendered html element?

My question is about conditional rendering in JSX and usage this

.

In my React app, consider the following code:

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

      

I would like to conditionally render the attribute onMouseEnter

so that it is not applied every time the component is invoked and the tag is displayed <li>

.

For example:

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

      

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

Obviously, calling { this.renderMouseEvents() }

outside the HTML element accepts use this

.

Why is it this

invalid inside html element in JSX?

What's the correct / cleaner way to accomplish this conditional rendering in JSX?

Any help is appreciated, thanks!

+3


source to share


5 answers


What you wrote is not valid JSX syntax. Try this instead:

mouseEnterBehaviorEnabled()

is a function that returns true

or false

. This is where you put your logic when you want to mouseEnter

run.

Take a look at Assessing Short Circuits on MDN.

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

      




Surely you could 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 don't work, just return false and the rest will fail.

+1


source


Just insert your condition into the attribute:



import noop from 'lodash/noop';

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

      

+2


source


You can do this 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>
      

Run codeHide result


+1


source


You can use this

in JSX, I don't think this is a problem.

If the problem is this

, it could be inside your method renderMouseEvents

, are you bind

up to this

?

But I think it doesn't work because of what your method returns renderMouseEvents

. While it is possible to inject properties, to check it out, it might help:

Dynamic attribute in ReactJS

0


source


If I understand what you are asking, I believe the problem you are having is related to how JSX is converted to JavaScript.

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

      

converts to something similar to the following:

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

      

What you wrote is likely to be translated this way if yours renderMouseEvents()

returns { onMouseEnter: this.mouseEnter }

:

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

      

This is invalid JavaScript. The compiler tells you what it expects ...

(JavaScript distribution syntax) which will probably solve this problem.

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

0


source







All Articles