Skip to content

Commit

Permalink
Merge pull request #50 from nutboltu/feat/function-component
Browse files Browse the repository at this point in the history
Feat: Refactor class component to functional component with react hooks
  • Loading branch information
nutboltu authored Jul 5, 2021
2 parents 5fb6fa6 + f56e00e commit 7ed7f00
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 104 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
},
"env": {
"browser": true,
"es6": true
"es6": true,
"jest": true
},
"plugins": [
"react"
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ The component takes the following props.
| `classNames` | string | Additional classnames for the component |
| `searchText` | string | Initial search value of the input |
| `placeholder` | string | placeholder for the search input |
| `disabled` | boolean | Disabling the search input |
| `onChange` | _function_ | Callback function to invoke when the user press any key. The function should contain two parameters(value, event). |
| `onEnter` | _function_ | Callback function to invoke when the user press enter after pressing few keys. The function should contain two parameters(value, event). |
| `onSearchClick` | _function_ | Callback function to invoke when the user click the search button. The function should contain one parameter(value). |
Expand Down Expand Up @@ -54,4 +55,4 @@ npm start

## License

MIT Licensed. Copyright (c) Farhad Yasir 2018.
MIT Licensed. Copyright (c) Farhad Yasir 2021.
2 changes: 1 addition & 1 deletion dist/index.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion docs/bundle.min.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-search-field",
"version": "1.2.1",
"version": "2.0.0",
"description": "This is a simple search field component for react",
"main": "dist/index.min.js",
"scripts": {
Expand All @@ -25,8 +25,8 @@
},
"dependencies": {
"prop-types": "15.7.2",
"react": "16.6.3",
"react-dom": "16.6.3",
"react": "16.9.0",
"react-dom": "16.9.0",
"react-github-btn": "1.2.0",
"typeco": "1.0.0"
},
Expand Down
152 changes: 72 additions & 80 deletions src/components/SearchField.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import PropTypes from 'prop-types';
import TypeChecker from 'typeco';

Expand All @@ -12,18 +12,18 @@ const searchFieldStyle = {
height: SEARCH_BUTTON_EDGE,
};

const searchFieldButtonStyle = {
const searchFieldButtonStyle = (disabled) => ({
height: SEARCH_BUTTON_EDGE - 2, // reduces 2px because of top and bottom border
width: SEARCH_BUTTON_EDGE - 2,
outline: 'none',
backgroundColor: 'white',
cursor: 'pointer',
cursor: disabled ? 'auto' : 'pointer',
padding: 5,
boxSizing: 'border-box',
appearance: 'none',
border: 'none',
borderLeft: '1px #ddd solid',
};
});

const searchFieldInputStyle = {
outline: 'none',
Expand Down Expand Up @@ -63,95 +63,86 @@ const SearchIcon = () => {
);
};

class SearchField extends React.Component {
constructor(props) {
super(props);
this.state = {
value: this.props.searchText,
};

this.onChangeBound = this.onChangeBound.bind(this);
this.onEnterBound = this.onEnterBound.bind(this);
this.onSearchClick = this.onSearchClick.bind(this);
this.onBlurBound = this.onBlurBound.bind(this);
}

componentWillReceiveProps(nextProps) {
if (this.props.searchText !== nextProps.searchText) {
this.setState({
value: nextProps.searchText,
});
}
}

onChangeBound(event) {
this.setState({
value: event.target.value,
});
if (TypeChecker.isFunction(this.props.onChange)) {
this.props.onChange(event.target.value, event);
const SearchField = ({
classNames,
searchText,
placeholder,
disabled,
onChange,
onEnter,
onSearchClick,
onBlur,
}) => {
const [value, setValue] = useState(searchText);

useEffect(() => {
setValue(searchText);
}, [searchText, setValue]);

const onChangeHandler = useCallback((event) => {
setValue(event.target.value);
if (TypeChecker.isFunction(onChange)) {
onChange(event.target.value, event);
}
}
}, [onChange, setValue]);

onEnterBound(event) {
const isEnterPressed = event.which === ENTER_KEY || event.keyCode === ENTER_KEY;
if (isEnterPressed && TypeChecker.isFunction(this.props.onEnter)) {
this.props.onEnter(event.target.value, event);
const onEnterHandler = useCallback((event) => {
const isEnterPressed = event.which === ENTER_KEY ||
event.keyCode === ENTER_KEY;
if (isEnterPressed && TypeChecker.isFunction(onEnter)) {
onEnter(event.target.value, event);
}
}
}, [onEnter]);

onSearchClick() {
if (TypeChecker.isFunction(this.props.onSearchClick)) {
this.props.onSearchClick(this.state.value);
const onSearchClickHandler = useCallback(() => {
if (TypeChecker.isFunction(onSearchClick)) {
onSearchClick(value);
}
}
}, [onSearchClick]);

onBlurBound(event) {
if (TypeChecker.isFunction(this.props.onBlur)) {
this.props.onBlur(event.target.value, event);
const onBlurHandler = useCallback((event) => {
if (TypeChecker.isFunction(onBlur)) {
onBlur(event.target.value, event);
}
}

render() {
const {
classNames,
placeholder,
} = this.props;
const className = `react-search-field ${classNames}`;

return (
<div
className={className}
style={searchFieldStyle}
}, [onBlur]);

const className = `react-search-field ${classNames}`;

return (
<div
className={className}
style={searchFieldStyle}
>
<input
className="react-search-field-input"
style={searchFieldInputStyle}
onChange={onChangeHandler}
onKeyPress={onEnterHandler}
onBlur={onBlurHandler}
placeholder={placeholder}
type="text"
value={value}
disabled={disabled}
/>
<button
className="react-search-field-button"
type="button"
aria-label="search button"
style={searchFieldButtonStyle(disabled)}
onClick={onSearchClickHandler}
disabled={disabled}
>
<input
className="react-search-field-input"
style={searchFieldInputStyle}
onChange={this.onChangeBound}
onKeyPress={this.onEnterBound}
onBlur={this.onBlurBound}
placeholder={placeholder}
type="text"
value={this.state.value}
/>
<button
className="react-search-field-button"
type="button"
aria-label="search button"
style={searchFieldButtonStyle}
onClick={this.onSearchClick}
>
<SearchIcon />
</button>
</div>
);
}
}
<SearchIcon />
</button>
</div>
);
};

SearchField.propTypes = {
classNames: PropTypes.string,
searchText: PropTypes.string,
placeholder: PropTypes.string,
disabled: PropTypes.bool,
onChange: PropTypes.func,
onEnter: PropTypes.func,
onSearchClick: PropTypes.func,
Expand All @@ -162,6 +153,7 @@ SearchField.defaultProps = {
classNames: '',
searchText: '',
placeholder: 'Search',
disabled: false,
onChange: null,
onEnter: null,
onSearchClick: null,
Expand Down
4 changes: 2 additions & 2 deletions src/docs/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ const exampleList = [

const getMatchedList = (searchText) => {
if (TypeChecker.isEmpty(searchText)) return exampleList;
return exampleList.filter(item => item.name.toLowerCase().includes(searchText.toLowerCase()));
return exampleList.filter((item) => item.name.toLowerCase().includes(searchText.toLowerCase()));
};

const ExampleList = props => (
const ExampleList = (props) => (
<div className="list-example">
<div className="list-header">
<ul>
Expand Down
2 changes: 1 addition & 1 deletion tests/SearchField.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('<SearchField />', () => {
it('should render searchText', () => {
const searchText = 'testSearchText';
const component = shallow(<SearchField searchText={searchText} />);
expect(component.children().at(0).props().value).toEqual(searchText);
expect(component.find('input').props().value).toEqual(searchText);
});
it('should render search button', () => {
const component = shallow(<SearchField />);
Expand Down
Loading

0 comments on commit 7ed7f00

Please sign in to comment.