SearchBox: migrate to Functional Component

This commit is contained in:
Jesse Chan
2021-01-20 21:46:22 +08:00
parent 68819ba64c
commit c66dd49518
2 changed files with 52 additions and 83 deletions
+3 -8
View File
@@ -1,4 +1,3 @@
import debounce from 'lodash/debounce';
import {MouseEvent, TouchEvent} from 'react';
import type {TorrentStatus} from '@shared/constants/torrentStatusMap';
@@ -46,13 +45,9 @@ const UIActions = {
TorrentFilterStore.setTrackerFilter(tracker);
},
setTorrentsSearchFilter: debounce(
(search: string) => {
TorrentFilterStore.setSearchFilter(search);
},
250,
{trailing: true},
),
setTorrentsSearchFilter: (search: string) => {
TorrentFilterStore.setSearchFilter(search);
},
} as const;
export default UIActions;
@@ -1,88 +1,62 @@
import {Component, ChangeEvent} from 'react';
import classnames from 'classnames';
import {injectIntl, WrappedComponentProps} from 'react-intl';
import {reaction} from 'mobx';
import {FC, useEffect, useRef} from 'react';
import {observer} from 'mobx-react';
import {useIntl} from 'react-intl';
import {Close, Search} from '@client/ui/icons';
import TorrentFilterStore from '@client/stores/TorrentFilterStore';
import UIActions from '@client/actions/UIActions';
interface SearchBoxStates {
inputFieldKey: number;
isSearchActive: boolean;
}
const SearchBox: FC = observer(() => {
const intl = useIntl();
const inputRef = useRef<HTMLInputElement>(null);
class SearchBox extends Component<WrappedComponentProps, SearchBoxStates> {
constructor(props: WrappedComponentProps) {
super(props);
const {searchFilter} = TorrentFilterStore.filters;
reaction(
() => TorrentFilterStore.filters.searchFilter,
(searchFilter) => {
if (searchFilter === '') {
this.resetSearch();
}
},
);
useEffect(() => {
if (inputRef.current != null) {
if (searchFilter !== inputRef.current.value) {
inputRef.current.value = searchFilter;
}
}
}, [inputRef, searchFilter]);
this.state = {
inputFieldKey: 0,
isSearchActive: false,
};
}
const isSearchActive = searchFilter !== '';
handleSearchChange = (event: ChangeEvent<HTMLInputElement>) => {
const {value} = event.target;
this.setState({isSearchActive: value !== ''});
UIActions.setTorrentsSearchFilter(value);
};
handleResetClick = () => {
this.resetSearch();
UIActions.setTorrentsSearchFilter('');
};
resetSearch = () => {
this.setState((state) => ({
inputFieldKey: state.inputFieldKey + 1,
isSearchActive: false,
}));
};
render() {
const {intl} = this.props;
const {inputFieldKey, isSearchActive} = this.state;
let clearSearchButton = null;
const classes = classnames({
sidebar__item: true, // eslint-disable-line
search: true,
'is-in-use': isSearchActive,
});
if (isSearchActive) {
clearSearchButton = (
<button className="button search__reset-button" onClick={this.handleResetClick} type="button">
return (
<div
className={classnames({
sidebar__item: true, // eslint-disable-line
search: true,
'is-in-use': isSearchActive,
})}>
{isSearchActive && (
<button
className="button search__reset-button"
onClick={() => {
UIActions.setTorrentsSearchFilter('');
if (inputRef.current != null) {
inputRef.current.blur();
}
}}
type="button">
<Close />
</button>
);
}
)}
<Search />
<input
className="textbox"
ref={inputRef}
type="text"
placeholder={intl.formatMessage({
id: 'sidebar.search.placeholder',
})}
onChange={(event) => {
UIActions.setTorrentsSearchFilter(event.target.value);
}}
/>
</div>
);
});
return (
<div className={classes}>
{clearSearchButton}
<Search />
<input
className="textbox"
key={inputFieldKey}
type="text"
placeholder={intl.formatMessage({
id: 'sidebar.search.placeholder',
})}
onChange={this.handleSearchChange}
/>
</div>
);
}
}
export default injectIntl(SearchBox);
export default SearchBox;