diff --git a/src/webui/app.js b/src/webui/app.js
index e94468e5c..7631655d1 100644
--- a/src/webui/app.js
+++ b/src/webui/app.js
@@ -1,12 +1,5 @@
 import React, { Component, Fragment } from 'react';
 import isNil from 'lodash/isNil';
-import Button from '@material-ui/core/Button';
-import Dialog from '@material-ui/core/Dialog';
-import DialogActions from '@material-ui/core/DialogActions';
-import DialogContent from '@material-ui/core/DialogContent';
-import DialogTitle from '@material-ui/core/DialogTitle';
-import SnackbarContent from '@material-ui/core/SnackbarContent';
-import ErrorIcon from '@material-ui/icons/Error';
 
 import storage from './utils/storage';
 import logo from './utils/logo';
@@ -19,10 +12,8 @@ import Header from './components/Header';
 import { Container, Content } from './components/Layout';
 import Route from './router';
 import API from './utils/api';
-import { getDetailPageURL } from './utils/url';
 
 import './styles/main.scss';
-import classes from "./app.scss";
 import 'normalize.css';
 
 export default class App extends Component {
@@ -34,16 +25,7 @@ export default class App extends Component {
     showLoginModal: false,
     isUserLoggedIn: false,
     packages: [],
-    searchPackages: [],
-    filteredPackages: [],
-    search: '',
     isLoading: true,
-    showAlertDialog: false,
-    alertDialogContent: {
-      title: '',
-      message: '',
-      packages: []
-    },
   }
 
   componentDidMount() {
@@ -89,7 +71,6 @@ export default class App extends Component {
       }));
       this.setState({
         packages: transformedPackages, 
-        filteredPackages: transformedPackages,
         isLoading: false
       });
     } catch (error) {
@@ -149,31 +130,9 @@ export default class App extends Component {
         token,
       },
       isUserLoggedIn: true,  // close login modal after successful login
-      showLoginModal: false  // set isUserLoggedin to true
+      showLoginModal: false  // set isUserLoggedIn to true
     });
   }
-
-  handleFetchPackages = async ({ value }) => {
-    try {
-      this.req = await API.request(`/search/${encodeURIComponent(value)}`, 'GET');
-      const transformedPackages = this.req.map(({ name, ...others}) => ({
-        label: name,
-        ...others
-      }));
-      // Implement cancel feature later
-      if (this.state.search === value) {
-        this.setState({
-          searchPackages: transformedPackages
-        });
-      }
-    } catch (error) {
-      this.handleShowAlertDialog({
-        title: 'Warning',
-        message: `Unable to get search result: ${error.message}`
-      });
-    }
-  }
-
   /**
    * Logouts user
    * Required by: <Header />
@@ -187,112 +146,19 @@ export default class App extends Component {
     });
   }
 
-  handlePackagesClearRequested = () => {
-    this.setState({
-      searchPackages: []
-    });
-  };
-
-   // eslint-disable-next-line no-unused-vars
-   handleSearch = (_, { newValue }) => {
-    const { filteredPackages, packages, search } = this.state;
-    const value = newValue.trim();
-    this.setState({
-      search: value,
-      filteredPackages: value.length < search.length ? 
-        packages.filter(pkg => pkg.label.match(value)) : filteredPackages
-    });
-  };
-
-  handleKeyDown = event => {
-    if (event.key === 'Enter') {
-      const { filteredPackages, packages } = this.state;
-      const value = event.target.value.trim();
-      this.setState({
-        filteredPackages: value ? 
-        packages.filter(pkg => pkg.label.match(value)) : filteredPackages
-      });
-    }
-  }
-
-  // eslint-disable-next-line no-unused-vars
-  handleClickSearch = (_, { suggestionValue, method }) => {
-    switch(method) {
-      case 'click':
-      case 'enter':
-        window.location.href = getDetailPageURL(suggestionValue);
-      break;
-    }
-  }
-
-  handleShowAlertDialog = content => {
-    this.setState({
-      showAlertDialog: true,
-      alertDialogContent: content
-    });
-  }
-
-  handleDismissAlertDialog = () => {
-    this.setState({
-      showAlertDialog: false
-    });
-  };
-
   renderHeader = () => {
-    const { logoUrl, user, search, searchPackages } = this.state;
+    const { logoUrl, user, scope } = this.state;
     return (
       <Header 
         logo={logoUrl}
         username={user.username}
         toggleLoginModal={this.toggleLoginModal}
         onLogout={this.handleLogout}
-        onSearch={this.handleSearch}
-        onSuggestionsFetch={this.handleFetchPackages}
-        onCleanSuggestions={this.handlePackagesClearRequested}
-        onClick={this.handleClickSearch}
-        onKeyDown={this.handleKeyDown}
-        packages={searchPackages}
-        search={search}
+        scope={scope}
       />
     );
   }
   
-  renderAlertDialog = () => (
-    <Dialog
-      open={this.state.showAlertDialog}
-      onClose={this.handleDismissAlertDialog}
-    >
-      <DialogTitle id="alert-dialog-title">
-        {this.state.alertDialogContent.title}
-      </DialogTitle>
-      <DialogContent>
-        <SnackbarContent
-          className={classes.alertError}
-          message={
-            <div
-              id="client-snackbar"
-              className={classes.alertErrorMsg}
-            >
-              <ErrorIcon className={classes.alertIcon} />
-              <span>
-                {this.state.alertDialogContent.message}
-              </span>
-            </div>
-          }
-        />
-      </DialogContent>
-      <DialogActions>
-        <Button
-          onClick={this.handleDismissAlertDialog}
-          color="primary"
-          autoFocus
-        >
-          Ok
-        </Button>
-      </DialogActions>
-    </Dialog>
-  )
-
   renderLoginModal = () => {
     const { error, showLoginModal } = this.state;
     return (
@@ -307,7 +173,7 @@ export default class App extends Component {
   }
 
   render() {
-    const { isLoading, ...others } = this.state;
+    const { isLoading, isUserLoggedIn, packages } = this.state;
     return (
       <Container isLoading={isLoading}>
         {isLoading ? (
@@ -316,12 +182,11 @@ export default class App extends Component {
           <Fragment>
             {this.renderHeader()}
             <Content>
-              <Route {...others} />
+              <Route isUserLoggedIn={isUserLoggedIn} packages={packages} />
             </Content>
             <Footer />
           </Fragment>
         )}
-        {this.renderAlertDialog()}
         {this.renderLoginModal()}
       </Container>
     );
diff --git a/src/webui/components/AutoComplete/index.js b/src/webui/components/AutoComplete/index.js
index 558c9cfcd..54d8e449e 100644
--- a/src/webui/components/AutoComplete/index.js
+++ b/src/webui/components/AutoComplete/index.js
@@ -57,6 +57,20 @@ const renderSuggestion = (suggestion, { query, isHighlighted }): Node => {
   );
 };
 
+const renderMessage = (message): Node => {
+  return (
+    <MenuItem selected={false} component="div">
+      <div>{message}</div>
+    </MenuItem>
+  );
+};
+
+const SUGGESTIONS_RESPONSE = {
+  LOADING: 'Loading...',
+  FAILURE: 'Something went wrong.',
+  NO_RESULT: 'No results found.',
+};
+
 const AutoComplete = ({
   suggestions,
   startAdornment,
@@ -69,6 +83,10 @@ const AutoComplete = ({
   color,
   onClick,
   onKeyDown,
+  onBlur,
+  suggestionsLoading = false,
+  suggestionsLoaded = false,
+  suggestionsError = false,
 }: IProps): Node => {
   const autosuggestProps = {
     renderInputComponent,
@@ -90,10 +108,14 @@ const AutoComplete = ({
           disableUnderline,
           color,
           onKeyDown,
+          onBlur,
         }}
-        renderSuggestionsContainer={options => (
-          <Paper {...options.containerProps} square>
-            {options.children}
+        renderSuggestionsContainer={({ containerProps, children, query }) => (
+          <Paper {...containerProps} square>
+            {suggestionsLoaded && children === null && query && renderMessage(SUGGESTIONS_RESPONSE.NO_RESULT)}
+            {suggestionsLoading && query && renderMessage(SUGGESTIONS_RESPONSE.LOADING)}
+            {suggestionsError && renderMessage(SUGGESTIONS_RESPONSE.FAILURE)}
+            {children}
           </Paper>
         )}
         onSuggestionSelected={onClick}
diff --git a/src/webui/components/AutoComplete/types.js b/src/webui/components/AutoComplete/types.js
index aba6c7c8a..5162f96f4 100644
--- a/src/webui/components/AutoComplete/types.js
+++ b/src/webui/components/AutoComplete/types.js
@@ -7,16 +7,21 @@ import { InputAdornmentProps } from '@material-ui/core/InputAdornment';
 
 export interface IProps {
   suggestions: any[];
+  suggestionsLoading?: boolean;
+  suggestionsLoaded?: boolean;
+  suggestionsError?: boolean;
+  apiLoading?: boolean;
   color?: string;
   value?: string;
   placeholder?: string;
   startAdornment?: React.ComponentType<InputAdornmentProps>;
   disableUnderline?: boolean;
-  onChange?: (event: SyntheticKeyboardEvent<HTMLInputElement>) => void;
-  onSuggestionsFetch?: (event: SyntheticKeyboardEvent<HTMLInputElement>) => void;
+  onChange?: (event: SyntheticKeyboardEvent<HTMLInputElement>, { newValue: string, method: string }) => void;
+  onSuggestionsFetch?: ({ value: string }) => Promise<void>;
   onCleanSuggestions?: () => void;
-  onClick?: () => void;
+  onClick?: (event: SyntheticKeyboardEvent<HTMLInputElement>, { suggestionValue: any[], method: string }) => void;
   onKeyDown?: (event: SyntheticKeyboardEvent<HTMLInputElement>) => void;
+  onBlur?: (event: SyntheticKeyboardEvent<HTMLInputElement>) => void;
 }
 
 export interface IInputField {
diff --git a/src/webui/components/Header/index.js b/src/webui/components/Header/index.js
index 3f29b1de2..3bba1afaf 100644
--- a/src/webui/components/Header/index.js
+++ b/src/webui/components/Header/index.js
@@ -4,6 +4,8 @@
  */
 
 import React, { Component } from 'react';
+import type { Node } from 'react';
+
 import Button from '@material-ui/core/Button/index';
 import IconButton from '@material-ui/core/IconButton/index';
 import MenuItem from '@material-ui/core/MenuItem/index';
@@ -12,7 +14,6 @@ import Info from '@material-ui/icons/Info';
 import Help from '@material-ui/icons/Help';
 import Tooltip from '@material-ui/core/Tooltip/index';
 import AccountCircle from '@material-ui/icons/AccountCircle';
-import InputAdornment from '@material-ui/core/InputAdornment';
 import { default as IconSearch } from '@material-ui/icons/Search';
 
 import { getRegistryURL } from '../../utils/url';
@@ -20,13 +21,11 @@ import Link from '../Link';
 import Logo from '../Logo';
 import CopyToClipBoard from '../CopyToClipBoard/index';
 import RegistryInfoDialog from '../RegistryInfoDialog';
-import AutoComplete from '../AutoComplete';
 import Label from '../Label';
+import Search from '../Search';
 
-import type { Node } from 'react';
 import { IProps, IState } from './types';
-import colors from '../../utils/styles/colors';
-import { Greetings, NavBar, InnerNavBar, MobileNavBar, InnerMobileNavBar, LeftSide, RightSide, Search, IconSearchButton } from './styles';
+import { Greetings, NavBar, InnerNavBar, MobileNavBar, InnerMobileNavBar, LeftSide, RightSide, IconSearchButton, SearchWrapper } from './styles';
 
 class Header extends Component<IProps, IState> {
   handleLoggedInMenu: Function;
@@ -38,25 +37,13 @@ class Header extends Component<IProps, IState> {
 
   constructor(props: IProps) {
     super(props);
-    const { packages = [] } = props;
     this.state = {
       openInfoDialog: false,
       registryUrl: '',
-      packages,
       showMobileNavBar: false,
     };
   }
 
-  static getDerivedStateFromProps(nextProps: IProps, prevState: IState) {
-    if (nextProps.packages !== prevState.packages) {
-      return {
-        packages: nextProps.packages,
-      };
-    }
-
-    return null;
-  }
-
   componentDidMount() {
     const registryUrl = getRegistryURL();
     this.setState({
@@ -125,29 +112,16 @@ class Header extends Component<IProps, IState> {
   };
 
   renderLeftSide = (): Node => {
-    const { packages } = this.state;
-    const { onSearch = () => {}, search = '', withoutSearch = false, ...others } = this.props;
+    const { withoutSearch = false } = this.props;
     return (
       <LeftSide>
         <Link to="/" style={{ marginRight: '1em' }}>
           <Logo />
         </Link>
         {!withoutSearch && (
-          <Search>
-            <AutoComplete
-              suggestions={packages}
-              onChange={onSearch}
-              value={search}
-              placeholder="Search packages"
-              color={colors.white}
-              startAdornment={
-                <InputAdornment position="start" style={{ color: colors.white }}>
-                  <IconSearch />
-                </InputAdornment>
-              }
-              {...others}
-            />
-          </Search>
+          <SearchWrapper>
+            <Search />
+          </SearchWrapper>
         )}
       </LeftSide>
     );
@@ -238,8 +212,8 @@ class Header extends Component<IProps, IState> {
   };
 
   render() {
-    const { packages, showMobileNavBar } = this.state;
-    const { onSearch = () => {}, search = '', withoutSearch = false, ...others } = this.props;
+    const { showMobileNavBar } = this.state;
+    const { withoutSearch = false } = this.props;
     return (
       <div>
         <NavBar position="static">
@@ -253,7 +227,7 @@ class Header extends Component<IProps, IState> {
           !withoutSearch && (
             <MobileNavBar>
               <InnerMobileNavBar>
-                <AutoComplete suggestions={packages} onChange={onSearch} value={search} placeholder="Search packages" disableUnderline {...others} />
+                <Search />
               </InnerMobileNavBar>
               <Button color="inherit" onClick={this.handleDismissMNav}>
                 Cancel
diff --git a/src/webui/components/Header/styles.js b/src/webui/components/Header/styles.js
index 94fa67f15..422b1f159 100644
--- a/src/webui/components/Header/styles.js
+++ b/src/webui/components/Header/styles.js
@@ -80,7 +80,16 @@ export const InnerMobileNavBar = styled.div`
   }
 `;
 
-export const Search = styled.div`
+export const IconSearchButton = styled(IconButton)`
+  && {
+    display: block;
+    ${mq.medium(css`
+      display: none;
+    `)};
+  }
+`;
+
+export const SearchWrapper = styled.div`
   && {
     display: none;
     max-width: 393px;
@@ -91,12 +100,3 @@ export const Search = styled.div`
     `)};
   }
 `;
-
-export const IconSearchButton = styled(IconButton)`
-  && {
-    display: block;
-    ${mq.medium(css`
-      display: none;
-    `)};
-  }
-`;
diff --git a/src/webui/components/Header/types.js b/src/webui/components/Header/types.js
index 3c53b34c6..1c6335efa 100644
--- a/src/webui/components/Header/types.js
+++ b/src/webui/components/Header/types.js
@@ -8,16 +8,12 @@ export interface IProps {
   onLogout?: Function;
   toggleLoginModal: Function;
   scope: string;
-  search?: string;
-  packages?: any[];
   withoutSearch?: boolean;
-  onSearch?: (event: SyntheticKeyboardEvent<HTMLInputElement>) => void;
 }
 
 export interface IState {
   anchorEl?: any;
   openInfoDialog: boolean;
   registryUrl: string;
-  packages: any[];
   showMobileNavBar: boolean;
 }
diff --git a/src/webui/components/PackageList/index.js b/src/webui/components/PackageList/index.js
index 9782e50dc..cd3f4ec55 100644
--- a/src/webui/components/PackageList/index.js
+++ b/src/webui/components/PackageList/index.js
@@ -3,8 +3,7 @@ import PropTypes from 'prop-types';
 
 import Package from '../Package';
 import Help from '../Help';
-import NoItems from '../NoItems';
-import {formatAuthor, formatLicense} from '../../utils/package';
+import { formatAuthor, formatLicense } from '../../utils/package';
 
 import classes from './packageList.scss';
 
@@ -14,7 +13,7 @@ export default class PackageList extends React.Component {
     help: PropTypes.bool
   };
 
-  renderPackges = () => {
+  renderPackages = () => {
     const { packages } = this.props;
     return (
       packages.length > 0 ? (
@@ -22,12 +21,7 @@ export default class PackageList extends React.Component {
           <h1 className={classes.listTitle}>Available Packages</h1>
           {this.renderList()}
         </Fragment>
-      ) : (
-        <NoItems
-          className="package-no-items"
-          text={'No items were found with that query'}
-        />
-      )
+      ) : null
     );
   }
 
@@ -45,7 +39,7 @@ export default class PackageList extends React.Component {
             </li>
           );
         })}
-    </ul>
+      </ul>
     );
   }
 
@@ -54,9 +48,9 @@ export default class PackageList extends React.Component {
     return (
       <div className="package-list-items">
         <div className={classes.pkgContainer}>
-          {help ? <Help /> : this.renderPackges()}
+          {help ? <Help /> : this.renderPackages()}
         </div>
       </div>
     );
   }
-}
+}
\ No newline at end of file
diff --git a/src/webui/components/Search/index.js b/src/webui/components/Search/index.js
new file mode 100644
index 000000000..5874723de
--- /dev/null
+++ b/src/webui/components/Search/index.js
@@ -0,0 +1,185 @@
+/**
+ * @prettier
+ * @flow
+ */
+
+import React, { Component } from 'react';
+import type { Node } from 'react';
+
+import { default as IconSearch } from '@material-ui/icons/Search';
+import InputAdornment from '@material-ui/core/InputAdornment';
+import debounce from 'lodash/debounce';
+
+import API from '../../utils/api';
+import AutoComplete from '../AutoComplete';
+import colors from '../../utils/styles/colors';
+import { getDetailPageURL } from '../../utils/url';
+
+import { IProps, IState } from './types';
+import type { cancelAllSearchRequests, handlePackagesClearRequested, handleSearch, handleClickSearch, handleFetchPackages, onBlur } from './types';
+
+const CONSTANTS = {
+  API_DELAY: 300,
+  PLACEHOLDER_TEXT: 'Search Packages',
+  ABORT_ERROR: 'AbortError',
+};
+
+class Search extends Component<IProps, IState> {
+  requestList: Array<any>;
+
+  constructor(props: IProps) {
+    super(props);
+    this.state = {
+      search: '',
+      suggestions: [],
+      // loading: A boolean value to indicate that request is in pending state.
+      loading: false,
+      // loaded: A boolean value to indicate that result has been loaded.
+      loaded: false,
+      // error: A boolean value to indicate API error.
+      error: false,
+    };
+    this.requestList = [];
+    this.handleFetchPackages = debounce(this.handleFetchPackages, CONSTANTS.API_DELAY);
+  }
+
+  /**
+   * Cancel all the requests which are in pending state.
+   */
+  cancelAllSearchRequests: cancelAllSearchRequests = () => {
+    this.requestList.forEach(request => request.abort());
+    this.requestList = [];
+  };
+
+  /**
+   * Cancel all the request from list and make request list empty.
+   */
+  handlePackagesClearRequested: handlePackagesClearRequested = () => {
+    this.setState({
+      suggestions: [],
+    });
+  };
+
+  /**
+   * onChange method for the input element.
+   */
+  handleSearch: handleSearch = (event, { newValue, method }) => {
+    // stops event bubbling
+    event.stopPropagation();
+    if (method === 'type') {
+      const value = newValue.trim();
+      this.setState(
+        {
+          search: value,
+          loading: true,
+          loaded: false,
+          error: false,
+        },
+        () => {
+          /**
+           * A use case where User keeps adding and removing value in input field,
+           * so we cancel all the existing requests when input is empty.
+           */
+          if (value.length === 0) {
+            this.cancelAllSearchRequests();
+          }
+        }
+      );
+    }
+  };
+
+  /**
+   * When an user select any package by clicking or pressing return key.
+   */
+  handleClickSearch: handleClickSearch = (event, { suggestionValue, method }) => {
+    // stops event bubbling
+    event.stopPropagation();
+    switch (method) {
+      case 'click':
+      case 'enter':
+        this.setState({ search: '' });
+        window.location.href = getDetailPageURL(suggestionValue);
+        break;
+    }
+  };
+
+  /**
+   * Fetch packages from API.
+   * For AbortController see: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
+   */
+  handleFetchPackages: handleFetchPackages = async ({ value }) => {
+    try {
+      const controller = new window.AbortController();
+      const signal = controller.signal;
+      // Keep track of search requests.
+      this.requestList.push(controller);
+      const response = await API.request(`search/${encodeURIComponent(value)}`, 'GET', { signal });
+      this.setState({ loaded: true });
+      const transformedPackages = response.map(({ name, ...others }) => ({
+        label: name,
+        ...others,
+      }));
+      if (this.state.search === value) {
+        this.setState({
+          suggestions: transformedPackages,
+          loaded: true,
+        });
+      }
+    } catch (error) {
+      /**
+       * AbortError is not the API error.
+       * It means browser has cancelled the API request.
+       */
+      if (error.name !== CONSTANTS.ABORT_ERROR) {
+        this.setState({ error: true, loaded: false });
+      }
+    } finally {
+      this.setState({ loading: false });
+    }
+  };
+
+  /**
+   * As user focuses out from input, we cancel all the request from requestList
+   * and set the API state parameters to default boolean values.
+   */
+  onBlur: onBlur = event => {
+    // stops event bubbling
+    event.stopPropagation();
+    this.setState(
+      {
+        loaded: false,
+        loading: false,
+        error: false,
+      },
+      () => this.cancelAllSearchRequests()
+    );
+  };
+
+  render(): Node {
+    const { suggestions, search, loaded, loading, error } = this.state;
+
+    return (
+      <AutoComplete
+        suggestions={suggestions}
+        suggestionsLoaded={loaded}
+        suggestionsLoading={loading}
+        suggestionsError={error}
+        value={search}
+        placeholder={CONSTANTS.PLACEHOLDER_TEXT}
+        color={colors.white}
+        startAdornment={
+          <InputAdornment position="start" style={{ color: colors.white }}>
+            <IconSearch />
+          </InputAdornment>
+        }
+        onSuggestionsFetch={this.handleFetchPackages}
+        onCleanSuggestions={this.handlePackagesClearRequested}
+        onClick={this.handleClickSearch}
+        onChange={this.handleSearch}
+        onBlur={this.onBlur}
+      />
+    );
+  }
+}
+
+export default Search;
diff --git a/src/webui/components/Search/types.js b/src/webui/components/Search/types.js
new file mode 100644
index 000000000..80b21af65
--- /dev/null
+++ b/src/webui/components/Search/types.js
@@ -0,0 +1,21 @@
+/**
+ * @prettier
+ * @flow
+ */
+
+export interface IProps {}
+
+export interface IState {
+  search: string;
+  suggestions: any[];
+  loading: boolean;
+  loaded: boolean;
+  error: boolean;
+}
+
+export type cancelAllSearchRequests = () => void;
+export type handlePackagesClearRequested = () => void;
+export type handleSearch = (event: SyntheticKeyboardEvent<HTMLInputElement>, { newValue: string, method: string }) => void;
+export type handleClickSearch = (event: SyntheticKeyboardEvent<HTMLInputElement>, { suggestionValue: Array<Object>, method: string }) => void;
+export type handleFetchPackages = ({ value: string }) => Promise<void>;
+export type onBlur = (event: SyntheticKeyboardEvent<HTMLInputElement>) => void;
diff --git a/src/webui/pages/home/index.js b/src/webui/pages/home/index.js
index ec3dda5d4..84ea82fba 100644
--- a/src/webui/pages/home/index.js
+++ b/src/webui/pages/home/index.js
@@ -5,40 +5,15 @@ import PackageList from '../../components/PackageList';
 
 class Home extends Component {
   static propTypes = {
-    children: PropTypes.element,
-    isUserLoggedIn: PropTypes.bool,
-    packages: PropTypes.array,
-    filteredPackages: PropTypes.array,
+    isUserLoggedIn: PropTypes.bool.isRequired,
+    packages: PropTypes.array.isRequired,
   };
-
-  constructor(props) {
-    super(props);
-    this.state = {
-      fistTime: true,
-      packages: props.packages,
-      filteredPackages: props.filteredPackages
-    };
-  }
-
-  static getDerivedStateFromProps(nextProps, prevState) {
-    if (nextProps.packages !== prevState.packages) {
-      return {
-        packages: nextProps.packages,
-      };
-    }
-    if (nextProps.filteredPackages !== prevState.filteredPackages) {
-      return {
-        filteredPackages: nextProps.filteredPackages,
-      };
-    }
-    return null;
-  }
   
   render() {
-    const { filteredPackages, packages } = this.state;
+    const { packages } = this.props;
     return (
       <div className="container content">
-        <PackageList help={!packages.length > 0} packages={filteredPackages} />
+        <PackageList help={packages.length < 1} packages={packages} />
       </div>
     );
   }
diff --git a/src/webui/router.js b/src/webui/router.js
index 2afec6458..3750d4c00 100644
--- a/src/webui/router.js
+++ b/src/webui/router.js
@@ -1,43 +1,33 @@
-import React, {Component} from 'react';
-import PropTypes from 'prop-types';
-import {HashRouter as Router, Route, Switch} from 'react-router-dom';
+/**
+ * @prettier
+ * @flow
+ */
 
-import {asyncComponent} from './utils/asyncComponent';
+import React, { Component } from 'react';
+import { HashRouter as Router, Route, Switch } from 'react-router-dom';
+
+import { asyncComponent } from './utils/asyncComponent';
 
 const DetailPackage = asyncComponent(() => import('./pages/detail'));
-import HomePage from './pages/home';
+const HomePage = asyncComponent(() => import('./pages/home'));
 
-class RouterApp extends Component {
-  static propTypes = {
-    isUserLoggedIn: PropTypes.bool
-  };
+interface IProps {
+  isUserLoggedIn: boolean;
+  packages: Array<Object>;
+}
 
+interface IState {}
+
+class RouterApp extends Component<IProps, IState> {
   render() {
+    const { isUserLoggedIn, packages } = this.props;
     return (
       <Router>
-          <Switch>
-            <Route
-              exact
-              path="/"
-              render={() => (
-                <HomePage {...this.props} />
-              )}
-            />
-            <Route
-              exact
-              path="/detail/@:scope/:package"
-              render={(props) => (
-                <DetailPackage {...props} {...this.props} />
-              )}
-            />
-            <Route
-              exact
-              path="/detail/:package"
-              render={(props) => (
-                <DetailPackage {...props} {...this.props} />
-              )}
-            />
-          </Switch>
+        <Switch>
+          <Route exact path="/" render={() => <HomePage isUserLoggedIn={isUserLoggedIn} packages={packages} />} />
+          <Route exact path="/detail/@:scope/:package" render={props => <DetailPackage {...props} isUserLoggedIn={isUserLoggedIn} />} />
+          <Route exact path="/detail/:package" render={props => <DetailPackage {...props} isUserLoggedIn={isUserLoggedIn} />} />
+        </Switch>
       </Router>
     );
   }
diff --git a/src/webui/utils/api.js b/src/webui/utils/api.js
index a48067bde..81f841494 100644
--- a/src/webui/utils/api.js
+++ b/src/webui/utils/api.js
@@ -51,6 +51,9 @@ class API {
           } else {
             reject(body);
           }
+        })
+        .catch(error => {
+          reject(error);
         });
       });
     }