Migrate components/post_view/post_flag_icon/post_flag_icon.tsx from class to function component (#24187)
* Class to functional example 3 * Address feedback * Address feedback --------- Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
544ceeba3e
Коммит
c1c07ba1bb
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
// See LICENSE.txt for license information.
|
// See LICENSE.txt for license information.
|
||||||
|
|
||||||
import React from 'react';
|
import React, {useCallback, useEffect, useRef, useState} from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
@@ -19,79 +19,60 @@ export type Actions = {
|
|||||||
unflagPost: typeof unflagPost;
|
unflagPost: typeof unflagPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
type Props = {
|
||||||
location?: keyof typeof Locations;
|
location?: keyof typeof Locations;
|
||||||
postId: string;
|
postId: string;
|
||||||
isFlagged: boolean;
|
isFlagged: boolean;
|
||||||
actions: Actions;
|
actions: Actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
const PostFlagIcon = ({
|
||||||
a11yActive: boolean;
|
actions: {
|
||||||
}
|
flagPost,
|
||||||
|
unflagPost,
|
||||||
export default class PostFlagIcon extends React.PureComponent<Props, State> {
|
},
|
||||||
static defaultProps = {
|
|
||||||
location: Locations.CENTER,
|
|
||||||
};
|
|
||||||
|
|
||||||
private buttonRef: React.RefObject<HTMLButtonElement>;
|
|
||||||
|
|
||||||
constructor(props: Props) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this.buttonRef = React.createRef();
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
a11yActive: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
if (this.buttonRef.current) {
|
|
||||||
this.buttonRef.current.addEventListener(A11yCustomEventTypes.ACTIVATE, this.handleA11yActivateEvent);
|
|
||||||
this.buttonRef.current.addEventListener(A11yCustomEventTypes.DEACTIVATE, this.handleA11yDeactivateEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this.buttonRef.current) {
|
|
||||||
this.buttonRef.current.removeEventListener(A11yCustomEventTypes.ACTIVATE, this.handleA11yActivateEvent);
|
|
||||||
this.buttonRef.current.removeEventListener(A11yCustomEventTypes.DEACTIVATE, this.handleA11yDeactivateEvent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
if (this.state.a11yActive && this.buttonRef.current) {
|
|
||||||
this.buttonRef.current.dispatchEvent(new Event(A11yCustomEventTypes.UPDATE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handlePress = (e: React.MouseEvent) => {
|
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
const {
|
|
||||||
actions,
|
|
||||||
isFlagged,
|
isFlagged,
|
||||||
postId,
|
postId,
|
||||||
} = this.props;
|
location = Locations.CENTER,
|
||||||
|
}: Props) => {
|
||||||
|
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||||
|
const [a11yActive, setA11yActive] = useState(false);
|
||||||
|
|
||||||
|
const handlePress = useCallback((e: React.MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
if (isFlagged) {
|
if (isFlagged) {
|
||||||
actions.unflagPost(postId);
|
unflagPost(postId);
|
||||||
} else {
|
} else {
|
||||||
actions.flagPost(postId);
|
flagPost(postId);
|
||||||
|
}
|
||||||
|
}, [flagPost, unflagPost, postId, isFlagged]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
function handleA11yActivateEvent() {
|
||||||
|
setA11yActive(true);
|
||||||
|
}
|
||||||
|
function handleA11yDeactivateEvent() {
|
||||||
|
setA11yActive(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonRef.current) {
|
||||||
|
buttonRef.current.addEventListener(A11yCustomEventTypes.ACTIVATE, handleA11yActivateEvent);
|
||||||
|
buttonRef.current.addEventListener(A11yCustomEventTypes.DEACTIVATE, handleA11yDeactivateEvent);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
if (buttonRef.current) {
|
||||||
|
buttonRef.current.removeEventListener(A11yCustomEventTypes.ACTIVATE, handleA11yActivateEvent);
|
||||||
|
buttonRef.current.removeEventListener(A11yCustomEventTypes.DEACTIVATE, handleA11yDeactivateEvent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
handleA11yActivateEvent = () => {
|
useEffect(() => {
|
||||||
this.setState({a11yActive: true});
|
if (a11yActive && buttonRef.current) {
|
||||||
};
|
buttonRef.current.dispatchEvent(new Event(A11yCustomEventTypes.UPDATE));
|
||||||
|
}
|
||||||
handleA11yDeactivateEvent = () => {
|
}, [a11yActive]);
|
||||||
this.setState({a11yActive: false});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const isFlagged = this.props.isFlagged;
|
|
||||||
|
|
||||||
let flagIcon;
|
let flagIcon;
|
||||||
if (isFlagged) {
|
if (isFlagged) {
|
||||||
@@ -119,15 +100,16 @@ export default class PostFlagIcon extends React.PureComponent<Props, State> {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
ref={this.buttonRef}
|
ref={buttonRef}
|
||||||
id={`${this.props.location}_flagIcon_${this.props.postId}`}
|
id={`${location}_flagIcon_${postId}`}
|
||||||
aria-label={isFlagged ? localizeMessage('flag_post.unflag', 'Remove from Saved').toLowerCase() : localizeMessage('flag_post.flag', 'Save').toLowerCase()}
|
aria-label={isFlagged ? localizeMessage('flag_post.unflag', 'Remove from Saved').toLowerCase() : localizeMessage('flag_post.flag', 'Save').toLowerCase()}
|
||||||
className='post-menu__item'
|
className='post-menu__item'
|
||||||
onClick={this.handlePress}
|
onClick={handlePress}
|
||||||
>
|
>
|
||||||
{flagIcon}
|
{flagIcon}
|
||||||
</button>
|
</button>
|
||||||
</OverlayTrigger>
|
</OverlayTrigger>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
export default React.memo(PostFlagIcon);
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user