admin管理员组

文章数量:1023738

I’m stuck using a jquery emoji plugin on one of my ponents until I finish with a custom plugin I’m building.

For some reason, when I call the emoji plugin inside of ponentDidMount, everything works except the ability to utilize a custom button to show the emoji modal. When I use a custom button, the emoji plugin doesn’t attach the event to the button.

What’s crazy is that I can use the same exact code in useEffect, and it attaches the event listener to the custom button just fine.

I verified that the event listener is not attached by looking in the web console at events attached to the element after the page loaded.

You can easily reproduce this problem by placing this ponent somewhere in an app (and importing jquery with the emoji-area plugin):

import React, {useEffect} from 'react';

  export default function CommentInput(props) {

    useEffect(() => {
      const id = props.blurtId,
            $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
          });


      $.emojiarea.path = '/js/jquery/emojis/';
      $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
      };

   }, []); 

   return (
     <>
        <textarea id={props.blurtId} className='blurt-ment-input' />
        <i id={'emoji-btn' + props.blurtId} className='fa fa-smile emoji-btn' />  
     </>
   )

}

Simply change this to a class ponent, and you’ll see that within ponentDidMount, everything works except the custom button. Any idea what could cause this change in behavior??

Here is the react class ponent version:

import React, {Component} from 'react';

class CommentInput extends Component {

constructor(props) {
    super(props);
}

ponentDidMount() {
    const id = this.props.blurtId,
          $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
        });


    $.emojiarea.path = '/js/jquery/emojis/';
    $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
    };
}; 

render() {
    return (
        <>
            <textarea id={this.props.blurtId} className='blurt-ment-input' />
            <i id={'emoji-btn' + this.props.blurtId} className='fa fa-smile emoji-btn' />  
        </>
      )
    }
}

export default CommentInput;

I’m stuck using a jquery emoji plugin on one of my ponents until I finish with a custom plugin I’m building.

For some reason, when I call the emoji plugin inside of ponentDidMount, everything works except the ability to utilize a custom button to show the emoji modal. When I use a custom button, the emoji plugin doesn’t attach the event to the button.

What’s crazy is that I can use the same exact code in useEffect, and it attaches the event listener to the custom button just fine.

I verified that the event listener is not attached by looking in the web console at events attached to the element after the page loaded.

You can easily reproduce this problem by placing this ponent somewhere in an app (and importing jquery with the emoji-area plugin):

import React, {useEffect} from 'react';

  export default function CommentInput(props) {

    useEffect(() => {
      const id = props.blurtId,
            $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
          });


      $.emojiarea.path = '/js/jquery/emojis/';
      $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
      };

   }, []); 

   return (
     <>
        <textarea id={props.blurtId} className='blurt-ment-input' />
        <i id={'emoji-btn' + props.blurtId} className='fa fa-smile emoji-btn' />  
     </>
   )

}

Simply change this to a class ponent, and you’ll see that within ponentDidMount, everything works except the custom button. Any idea what could cause this change in behavior??

Here is the react class ponent version:

import React, {Component} from 'react';

class CommentInput extends Component {

constructor(props) {
    super(props);
}

ponentDidMount() {
    const id = this.props.blurtId,
          $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
        });


    $.emojiarea.path = '/js/jquery/emojis/';
    $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
    };
}; 

render() {
    return (
        <>
            <textarea id={this.props.blurtId} className='blurt-ment-input' />
            <i id={'emoji-btn' + this.props.blurtId} className='fa fa-smile emoji-btn' />  
        </>
      )
    }
}

export default CommentInput;
Share Improve this question edited Aug 28, 2019 at 17:12 silencedogood asked Aug 28, 2019 at 17:03 silencedogoodsilencedogood 3,2991 gold badge15 silver badges38 bronze badges 7
  • Since the code you're having trouble with is with a class ponent, we can't really help you if you don't show us that code. – T.J. Crowder Commented Aug 28, 2019 at 17:05
  • Please update your question with a minimal reproducible example demonstrating the problem, ideally a runnable one using Stack Snippets (the [<>] toolbar button). Stack Snippets support React, including JSX; here's how to do one. – T.J. Crowder Commented Aug 28, 2019 at 17:06
  • @T.J.Crowder It's literally the same exact code.. Just changed to a react class ponent.. And EVERYTHING works in the class except this button. However, I'll add the class ponent version even though I think it's a bit much. – silencedogood Commented Aug 28, 2019 at 17:07
  • 2 It isn't. :-) Remember, you're asking people to take time out of their day to help you. You want to make that as easy as possible. Thanks in advance for adding it, and as a runnable example. – T.J. Crowder Commented Aug 28, 2019 at 17:08
  • 1 @T.J.Crowder Ahhh, very cool. This will e in handy. Thanks! – silencedogood Commented Aug 28, 2019 at 17:19
 |  Show 2 more ments

2 Answers 2

Reset to default 5

There is a difference between when ponentDidMount and useEffect fires.

From the useEffect docs :

Unlike ponentDidMount and ponentDidUpdate, the function passed to useEffect fires after layout and paint

The big difference between ponentDidMount and useEffect is that useEffect is run after every render, not just the first one. Since your render outputs a new element on each render, after the first render the DOM element you attached the emoji thing to doesn't exist anymore, and a new one with the same ID does.

Options:

  • Use ponentDidUpdate to handle the subsequent renders. (You'll still need ponentDidMount for the first one.)
  • Use a callback ref.

I’m stuck using a jquery emoji plugin on one of my ponents until I finish with a custom plugin I’m building.

For some reason, when I call the emoji plugin inside of ponentDidMount, everything works except the ability to utilize a custom button to show the emoji modal. When I use a custom button, the emoji plugin doesn’t attach the event to the button.

What’s crazy is that I can use the same exact code in useEffect, and it attaches the event listener to the custom button just fine.

I verified that the event listener is not attached by looking in the web console at events attached to the element after the page loaded.

You can easily reproduce this problem by placing this ponent somewhere in an app (and importing jquery with the emoji-area plugin):

import React, {useEffect} from 'react';

  export default function CommentInput(props) {

    useEffect(() => {
      const id = props.blurtId,
            $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
          });


      $.emojiarea.path = '/js/jquery/emojis/';
      $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
      };

   }, []); 

   return (
     <>
        <textarea id={props.blurtId} className='blurt-ment-input' />
        <i id={'emoji-btn' + props.blurtId} className='fa fa-smile emoji-btn' />  
     </>
   )

}

Simply change this to a class ponent, and you’ll see that within ponentDidMount, everything works except the custom button. Any idea what could cause this change in behavior??

Here is the react class ponent version:

import React, {Component} from 'react';

class CommentInput extends Component {

constructor(props) {
    super(props);
}

ponentDidMount() {
    const id = this.props.blurtId,
          $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
        });


    $.emojiarea.path = '/js/jquery/emojis/';
    $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
    };
}; 

render() {
    return (
        <>
            <textarea id={this.props.blurtId} className='blurt-ment-input' />
            <i id={'emoji-btn' + this.props.blurtId} className='fa fa-smile emoji-btn' />  
        </>
      )
    }
}

export default CommentInput;

I’m stuck using a jquery emoji plugin on one of my ponents until I finish with a custom plugin I’m building.

For some reason, when I call the emoji plugin inside of ponentDidMount, everything works except the ability to utilize a custom button to show the emoji modal. When I use a custom button, the emoji plugin doesn’t attach the event to the button.

What’s crazy is that I can use the same exact code in useEffect, and it attaches the event listener to the custom button just fine.

I verified that the event listener is not attached by looking in the web console at events attached to the element after the page loaded.

You can easily reproduce this problem by placing this ponent somewhere in an app (and importing jquery with the emoji-area plugin):

import React, {useEffect} from 'react';

  export default function CommentInput(props) {

    useEffect(() => {
      const id = props.blurtId,
            $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
          });


      $.emojiarea.path = '/js/jquery/emojis/';
      $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
      };

   }, []); 

   return (
     <>
        <textarea id={props.blurtId} className='blurt-ment-input' />
        <i id={'emoji-btn' + props.blurtId} className='fa fa-smile emoji-btn' />  
     </>
   )

}

Simply change this to a class ponent, and you’ll see that within ponentDidMount, everything works except the custom button. Any idea what could cause this change in behavior??

Here is the react class ponent version:

import React, {Component} from 'react';

class CommentInput extends Component {

constructor(props) {
    super(props);
}

ponentDidMount() {
    const id = this.props.blurtId,
          $wysiwyg = $('#' + id).emojiarea({
            button: '#emoji-btn' + id
        });


    $.emojiarea.path = '/js/jquery/emojis/';
    $.emojiarea.icons = {
        ':smile:'     : 'smile.png',
        ':angry:'     : 'angry.png',
        ':flushed:'   : 'flushed.png',
        ':neckbeard:' : 'neckbeard.png',
        ':laughing:'  : 'laughing.png'
    };
}; 

render() {
    return (
        <>
            <textarea id={this.props.blurtId} className='blurt-ment-input' />
            <i id={'emoji-btn' + this.props.blurtId} className='fa fa-smile emoji-btn' />  
        </>
      )
    }
}

export default CommentInput;
Share Improve this question edited Aug 28, 2019 at 17:12 silencedogood asked Aug 28, 2019 at 17:03 silencedogoodsilencedogood 3,2991 gold badge15 silver badges38 bronze badges 7
  • Since the code you're having trouble with is with a class ponent, we can't really help you if you don't show us that code. – T.J. Crowder Commented Aug 28, 2019 at 17:05
  • Please update your question with a minimal reproducible example demonstrating the problem, ideally a runnable one using Stack Snippets (the [<>] toolbar button). Stack Snippets support React, including JSX; here's how to do one. – T.J. Crowder Commented Aug 28, 2019 at 17:06
  • @T.J.Crowder It's literally the same exact code.. Just changed to a react class ponent.. And EVERYTHING works in the class except this button. However, I'll add the class ponent version even though I think it's a bit much. – silencedogood Commented Aug 28, 2019 at 17:07
  • 2 It isn't. :-) Remember, you're asking people to take time out of their day to help you. You want to make that as easy as possible. Thanks in advance for adding it, and as a runnable example. – T.J. Crowder Commented Aug 28, 2019 at 17:08
  • 1 @T.J.Crowder Ahhh, very cool. This will e in handy. Thanks! – silencedogood Commented Aug 28, 2019 at 17:19
 |  Show 2 more ments

2 Answers 2

Reset to default 5

There is a difference between when ponentDidMount and useEffect fires.

From the useEffect docs :

Unlike ponentDidMount and ponentDidUpdate, the function passed to useEffect fires after layout and paint

The big difference between ponentDidMount and useEffect is that useEffect is run after every render, not just the first one. Since your render outputs a new element on each render, after the first render the DOM element you attached the emoji thing to doesn't exist anymore, and a new one with the same ID does.

Options:

  • Use ponentDidUpdate to handle the subsequent renders. (You'll still need ponentDidMount for the first one.)
  • Use a callback ref.

本文标签: