使用 jquery 表情符号插件时,componentDidMount 的行为与 useEffect 不同
different behavior with componentDidMount than useEffect when using jquery emoji plugin
我无法在我的一个组件上使用 jquery 表情符号插件,直到我完成我正在构建的自定义插件。
出于某种原因,当我在 componentDidMount 中调用表情符号插件时,一切正常 除了 使用自定义按钮显示表情符号模式的能力。当我使用自定义按钮时,表情符号插件不会将事件附加到按钮。
令人疯狂的是,我可以在 useEffect 中使用完全相同的代码,并将事件侦听器附加到自定义按钮上就好了。
我通过在 Web 控制台中查看页面加载后附加到元素的事件来验证未附加事件侦听器。
您可以通过将此组件放置在应用中的某处(并使用 emoji-area plugin 导入 jquery 来轻松重现此问题:
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-comment-input' />
<i id={'emoji-btn' + props.blurtId} className='fa fa-smile emoji-btn' />
</>
)
}
只需将其更改为 class 组件,您将看到在 componentDidMount 中,除自定义按钮外,一切正常。知道什么会导致这种行为改变吗?
这里是 react class 组件版本:
import React, {Component} from 'react';
class CommentInput extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
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-comment-input' />
<i id={'emoji-btn' + this.props.blurtId} className='fa fa-smile emoji-btn' />
</>
)
}
}
export default CommentInput;
componentDidMount
and useEffect
之间的最大区别在于 useEffect
是 运行 在 每个 渲染之后,而不仅仅是第一个渲染。由于您的 render
在每个渲染器上输出一个 new 元素,因此在第一次渲染后,您附加表情符号的 DOM 元素不再存在,并且具有相同 ID 的新用户。
选项:
- 使用
componentDidUpdate
处理后续渲染。 (第一个仍然需要 componentDidMount
。)
- 使用 callback ref.
componentDidMount
和 useEffect
触发时有区别。
来自 useEffect 文档:
Unlike componentDidMount and componentDidUpdate, the function passed
to useEffect fires after layout and paint
我无法在我的一个组件上使用 jquery 表情符号插件,直到我完成我正在构建的自定义插件。
出于某种原因,当我在 componentDidMount 中调用表情符号插件时,一切正常 除了 使用自定义按钮显示表情符号模式的能力。当我使用自定义按钮时,表情符号插件不会将事件附加到按钮。
令人疯狂的是,我可以在 useEffect 中使用完全相同的代码,并将事件侦听器附加到自定义按钮上就好了。
我通过在 Web 控制台中查看页面加载后附加到元素的事件来验证未附加事件侦听器。
您可以通过将此组件放置在应用中的某处(并使用 emoji-area plugin 导入 jquery 来轻松重现此问题:
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-comment-input' />
<i id={'emoji-btn' + props.blurtId} className='fa fa-smile emoji-btn' />
</>
)
}
只需将其更改为 class 组件,您将看到在 componentDidMount 中,除自定义按钮外,一切正常。知道什么会导致这种行为改变吗?
这里是 react class 组件版本:
import React, {Component} from 'react';
class CommentInput extends Component {
constructor(props) {
super(props);
}
componentDidMount() {
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-comment-input' />
<i id={'emoji-btn' + this.props.blurtId} className='fa fa-smile emoji-btn' />
</>
)
}
}
export default CommentInput;
componentDidMount
and useEffect
之间的最大区别在于 useEffect
是 运行 在 每个 渲染之后,而不仅仅是第一个渲染。由于您的 render
在每个渲染器上输出一个 new 元素,因此在第一次渲染后,您附加表情符号的 DOM 元素不再存在,并且具有相同 ID 的新用户。
选项:
- 使用
componentDidUpdate
处理后续渲染。 (第一个仍然需要componentDidMount
。) - 使用 callback ref.
componentDidMount
和 useEffect
触发时有区别。
来自 useEffect 文档:
Unlike componentDidMount and componentDidUpdate, the function passed to useEffect fires after layout and paint