react-autosuggest vs react-select vs selectize
Implementing Search Inputs and Dropdown Selectors in React
react-autosuggestreact-selectselectizeSimilar Packages:

Implementing Search Inputs and Dropdown Selectors in React

react-autosuggest, react-select, and selectize address user input patterns involving suggestions and selections, but they solve different problems with distinct architectures. react-autosuggest is a pure React component designed specifically for autocomplete input fields where users type to get suggestions. react-select is a comprehensive React-based select control that supports filtering, multi-selection, and async loading without external dependencies. selectize is a jQuery-based hybrid input/select plugin that requires DOM manipulation wrappers to function within React, making it fundamentally different from the other two React-native solutions.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-autosuggest05,935-2596 years agoMIT
react-select028,020726 kB491a year agoMIT
selectize013,018-378 years agoApache-2.0

React Input Solutions: react-autosuggest vs react-select vs selectize

When building forms in React, handling user input that involves suggestions or selections is a common requirement. react-autosuggest, react-select, and selectize each offer a different approach to this problem. Understanding their architectural differences is critical for making the right choice for your project.

๐Ÿ—๏ธ Core Architecture: React-Native vs jQuery

The most significant difference lies in how these libraries interact with the DOM. react-autosuggest and react-select are built specifically for React, meaning they rely on state and props to manage UI changes. selectize is built on jQuery, requiring direct DOM manipulation that bypasses React's rendering cycle.

react-autosuggest uses standard React props to control the input and suggestion list.

import Autosuggest from 'react-autosuggest';

function App() {
  const [value, setValue] = useState('');
  const [suggestions, setSuggestions] = useState([]);

  const onSuggestionsFetchRequested = ({ value }) => {
    setSuggestions(getSuggestions(value));
  };

  return (
    <Autosuggest
      suggestions={suggestions}
      onSuggestionsFetchRequested={onSuggestionsFetchRequested}
      inputProps={{ value, onChange: (e, { newValue }) => setValue(newValue) }}
    />
  );
}

react-select manages its own internal state but exposes controlled props for integration.

import Select from 'react-select';

function App() {
  const options = [
    { value: 'chocolate', label: 'Chocolate' },
    { value: 'strawberry', label: 'Strawberry' }
  ];

  return <Select options={options} />;
}

selectize requires a ref and useEffect to initialize the jQuery plugin on a DOM node.

import $ from 'jquery';
import 'selectize';

function App() {
  const ref = useRef(null);

  useEffect(() => {
    $(ref.current).selectize({
      options: [
        { value: 1, text: 'One' },
        { value: 2, text: 'Two' }
      ]
    });
  }, []);

  return <select ref={ref} />;
}

๐Ÿ”„ Handling Async Data Loading

Fetching options from an API is a common real-world scenario. The approach varies significantly between these packages.

react-autosuggest handles async suggestions via the fetch request callback.

const onSuggestionsFetchRequested = ({ value }) => {
  fetch(`/api/search?q=${value}`)
    .then(res => res.json())
    .then(data => setSuggestions(data));
};

<Autosuggest
  suggestions={suggestions}
  onSuggestionsFetchRequested={onSuggestionsFetchRequested}
  // ... other props
/>

react-select has a dedicated Async component built for this purpose.

import AsyncSelect from 'react-select/async';

const loadOptions = (inputValue) => {
  return fetch(`/api/search?q=${inputValue}`)
    .then(res => res.json());
};

<AsyncSelect loadOptions={loadOptions} />;

selectize handles async data via its API methods after initialization.

useEffect(() => {
  const selectize = $(ref.current)[0].selectize;
  
  // Load options dynamically
  fetch('/api/options').then(res => res.json()).then(data => {
    selectize.addOption(data);
    selectize.refreshOptions();
  });
}, []);

๐ŸŽจ Customization and Styling

Styling input components often requires overriding default themes. The effort required depends on the library's architecture.

react-autosuggest uses standard CSS classes you can target in your stylesheet.

/* Custom CSS file */
.react-autosuggest__suggestion {
  background-color: #f0f0f0;
  padding: 10px;
}

.react-autosuggest__suggestion--highlighted {
  background-color: #ddd;
}

react-select uses a JavaScript-based styles prop for dynamic theming.

const customStyles = {
  control: (provided) => ({
    ...provided,
    borderColor: 'blue'
  })
};

<Select styles={customStyles} options={options} />;

selectize relies on CSS classes and jQuery UI themes.

/* Custom CSS file */
.selectize-input {
  border: 1px solid #ccc;
}

.selectize-dropdown {
  background: #fff;
}

โš ๏ธ Maintenance and Ecosystem Health

Long-term project health depends on the library's maintenance status.

react-autosuggest is stable but sees less frequent updates compared to newer hooks-based libraries. It is considered mature but not actively evolving with the latest React features.

react-select is actively maintained with regular updates, strong TypeScript support, and a large community. It is the industry standard for React selects.

selectize is largely considered legacy. The original repository has seen minimal activity, and many developers have migrated to forks like tom-select for better maintenance and lack of jQuery dependency.

๐Ÿ“Š Summary Table

Featurereact-autosuggestreact-selectselectize
Frameworkโš›๏ธ React Nativeโš›๏ธ React Native๐Ÿ˜ jQuery Plugin
Primary Use๐Ÿ” Input Suggestions๐Ÿ“‹ Dropdown Selection๐Ÿ”„ Hybrid Input/Select
Async Supportโœ… Manual Fetchโœ… Built-in Async Componentโœ… Via API Methods
Styling๐ŸŽจ CSS Classes๐ŸŽจ JS Styles Prop๐ŸŽจ CSS Classes
Maintenance๐ŸŸก Stable / Low Activity๐ŸŸข Active / High Support๐Ÿ”ด Legacy / Low Activity
Dependencies๐Ÿ“ฆ None๐Ÿ“ฆ None๐Ÿ“ฆ jQuery Required

๐Ÿ’ก Final Recommendation

For modern React applications, react-select is the strongest choice for dropdowns and complex selection needs due to its active maintenance and deep React integration. Use react-autosuggest if you specifically need a lightweight autocomplete input without the overhead of a full select component. Avoid selectize in new projects unless you are constrained by legacy jQuery requirements, as its architecture fights against React's data flow model.

Final Thought: Prioritize React-native solutions to ensure your application remains maintainable and compatible with future React updates.

How to Choose: react-autosuggest vs react-select vs selectize

  • react-autosuggest:

    Choose react-autosuggest if you need a lightweight, dedicated solution for input suggestion fields like search bars where the user types to see hints. It is ideal when you do not need a full dropdown selection experience but rather want to guide user input with dynamic suggestions. Be aware that it requires more manual wiring for state management compared to newer hooks-based alternatives.

  • react-select:

    Choose react-select if you need a robust, feature-rich dropdown selector that supports multi-select, async data loading, and complex customization within a React ecosystem. It is the standard choice for forms requiring reliable accessibility and strict React state integration without jQuery dependencies. This package is best for teams prioritizing long-term maintenance and extensive community support.

  • selectize:

    Choose selectize only if you are maintaining a legacy application already dependent on jQuery or require specific features not found in modern React libraries. It is generally not recommended for new React projects due to its reliance on direct DOM manipulation and jQuery, which conflicts with React's virtual DOM approach. Consider modern forks like tom-select if you must use this architecture.

README for react-autosuggest

Build Status Contributors Coverage Status

npm Downloads npm Version gzip size

React Autosuggest

Project Status

Looking for maintainers!

Unfortunately, I don't have the time to maintain this project anymore. If you are interested to help, please reach out to me on Twitter @moroshko.

Demo

Check out the Homepage and the Codepen examples.

Features

Installation

yarn add react-autosuggest

or

npm install react-autosuggest --save

You can also use the standalone UMD build:

<script src="https://unpkg.com/react-autosuggest/dist/standalone/autosuggest.js"></script>

Basic Usage

import React from 'react';
import Autosuggest from 'react-autosuggest';

// Imagine you have a list of languages that you'd like to autosuggest.
const languages = [
  {
    name: 'C',
    year: 1972
  },
  {
    name: 'Elm',
    year: 2012
  },
  ...
];

// Teach Autosuggest how to calculate suggestions for any given input value.
const getSuggestions = value => {
  const inputValue = value.trim().toLowerCase();
  const inputLength = inputValue.length;

  return inputLength === 0 ? [] : languages.filter(lang =>
    lang.name.toLowerCase().slice(0, inputLength) === inputValue
  );
};

// When suggestion is clicked, Autosuggest needs to populate the input
// based on the clicked suggestion. Teach Autosuggest how to calculate the
// input value for every given suggestion.
const getSuggestionValue = suggestion => suggestion.name;

// Use your imagination to render suggestions.
const renderSuggestion = suggestion => (
  <div>
    {suggestion.name}
  </div>
);

class Example extends React.Component {
  constructor() {
    super();

    // Autosuggest is a controlled component.
    // This means that you need to provide an input value
    // and an onChange handler that updates this value (see below).
    // Suggestions also need to be provided to the Autosuggest,
    // and they are initially empty because the Autosuggest is closed.
    this.state = {
      value: '',
      suggestions: []
    };
  }

  onChange = (event, { newValue }) => {
    this.setState({
      value: newValue
    });
  };

  // Autosuggest will call this function every time you need to update suggestions.
  // You already implemented this logic above, so just use it.
  onSuggestionsFetchRequested = ({ value }) => {
    this.setState({
      suggestions: getSuggestions(value)
    });
  };

  // Autosuggest will call this function every time you need to clear suggestions.
  onSuggestionsClearRequested = () => {
    this.setState({
      suggestions: []
    });
  };

  render() {
    const { value, suggestions } = this.state;

    // Autosuggest will pass through all these props to the input.
    const inputProps = {
      placeholder: 'Type a programming language',
      value,
      onChange: this.onChange
    };

    // Finally, render it!
    return (
      <Autosuggest
        suggestions={suggestions}
        onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
        onSuggestionsClearRequested={this.onSuggestionsClearRequested}
        getSuggestionValue={getSuggestionValue}
        renderSuggestion={renderSuggestion}
        inputProps={inputProps}
      />
    );
  }
}

Props

PropTypeRequiredDescription
suggestionsArrayโœ“These are the suggestions that will be displayed. Items can take an arbitrary shape.
onSuggestionsFetchRequestedFunctionโœ“Will be called every time you need to recalculate suggestions.
onSuggestionsClearRequestedFunctionโœ“*Will be called every time you need to set suggestions to [].
getSuggestionValueFunctionโœ“Implement it to teach Autosuggest what should be the input value when suggestion is clicked.
renderSuggestionFunctionโœ“Use your imagination to define how suggestions are rendered.
inputPropsObjectโœ“Pass through arbitrary props to the input. It must contain at least value and onChange.
containerPropsObjectPass through arbitrary props to the container. Useful if you need to override the default props set by Autowhatever, for example, for accessibility.
onSuggestionSelectedFunctionWill be called every time suggestion is selected via mouse or keyboard.
onSuggestionHighlightedFunctionWill be called every time the highlighted suggestion changes.
shouldRenderSuggestionsFunctionWhen the input is focused, Autosuggest will consult this function when to render suggestions. Use it, for example, if you want to display suggestions when input value is at least 2 characters long.
alwaysRenderSuggestionsBooleanSet it to true if you'd like to render suggestions even when the input is not focused.
highlightFirstSuggestionBooleanSet it to true if you'd like Autosuggest to automatically highlight the first suggestion.
focusInputOnSuggestionClickBooleanSet it to false if you don't want Autosuggest to keep the input focused when suggestions are clicked/tapped.
multiSectionBooleanSet it to true if you'd like to display suggestions in multiple sections (with optional titles).
renderSectionTitleFunctionโœ“
when multiSection={true}
Use your imagination to define how section titles are rendered.
getSectionSuggestionsFunctionโœ“
when multiSection={true}
Implement it to teach Autosuggest where to find the suggestions for every section.
renderInputComponentFunctionUse it only if you need to customize the rendering of the input.
renderSuggestionsContainerFunctionUse it if you want to customize things inside the suggestions container beyond rendering the suggestions themselves.
themeObjectUse your imagination to style the Autosuggest.
idStringUse it only if you have multiple Autosuggest components on a page.

suggestions (required)

Array of suggestions to display. The only requirement is that suggestions is an array. Items in this array can take an arbitrary shape.

For a plain list of suggestions, every item in suggestions represents a single suggestion. It's up to you what shape every suggestion takes. For example:

const suggestions = [
  {
    text: "Apple"
  },
  {
    text: "Banana"
  },
  {
    text: "Cherry"
  },
  {
    text: "Grapefruit"
  },
  {
    text: "Lemon"
  }
];

For multiple sections, every item in suggestions represents a single section. Again, it's up to you what shape every section takes. For example:

const suggestions = [
  {
    title: "A",
    suggestions: [
      {
        id: "100",
        text: "Apple"
      },
      {
        id: "101",
        text: "Apricot"
      }
    ]
  },
  {
    title: "B",
    suggestions: [
      {
        id: "102",
        text: "Banana"
      }
    ]
  },
  {
    title: "C",
    suggestions: [
      {
        id: "103",
        text: "Cherry"
      }
    ]
  }
];

onSuggestionsFetchRequested (required)

This function will be called every time you might need to update suggestions. It has the following signature:

function onSuggestionsFetchRequested({ value, reason })

where:

  • value - the current value of the input
  • reason - string describing why onSuggestionsFetchRequested was called. The possible values are:
    • 'input-changed' - user typed something
    • 'input-focused' - input was focused
    • 'escape-pressed' - user pressed Escape to clear the input (and suggestions are shown for empty input)
    • 'suggestions-revealed' - user pressed Up or Down to reveal suggestions
    • 'suggestion-selected' - user selected a suggestion when alwaysRenderSuggestions={true}

onSuggestionsClearRequested (required unless alwaysRenderSuggestions={true})

This function will be called every time you need to clear suggestions.

All you have to do in this function is to set suggestions to [].

Note: When alwaysRenderSuggestions={true}, you don't have to implement this function.

getSuggestionValue (required)

When user navigates the suggestions using the Up and Down keys, the input value should be set according to the highlighted suggestion. You design how suggestion is modelled. Therefore, it's your responsibility to tell Autosuggest how to map suggestions to input values.

This function gets the suggestion in question, and it should return a string. For example:

function getSuggestionValue(suggestion) {
  return suggestion.text;
}

renderSuggestion (required)

Use your imagination to define how suggestions are rendered.

The signature is:

function renderSuggestion(suggestion, { query, isHighlighted })

where:

  • suggestion - The suggestion to render
  • query - Used to highlight the matching string. As user types in the input, query will be equal to the trimmed value of the input. Then, if user interacts using the Up or Down keys, the input will get the value of the highlighted suggestion, but query will remain to be equal to the trimmed value of the input prior to the Up and Down interactions.
  • isHighlighted - Whether or not the suggestion is highlighted.

It should return a string or a ReactElement. For example:

function renderSuggestion(suggestion) {
  return <span>{suggestion.text}</span>;
}

Important: renderSuggestion must be a pure function (we optimize rendering performance based on this assumption).

inputProps (required)

Autosuggest is a controlled component. Therefore, you MUST pass at least a value and an onChange callback to the input. You can pass any other props as well. For example:

const inputProps = {
  value, // usually comes from the application state
  onChange, // called every time the input value changes
  onBlur, // called when the input loses focus, e.g. when user presses Tab
  type: "search",
  placeholder: "Enter city or postcode"
};

inputProps.onChange (required)

The signature is:

function onChange(event, { newValue, method })

where:

  • newValue - the new value of the input
  • method - string describing how the change has occurred. The possible values are:
    • 'down' - user pressed Down
    • 'up' - user pressed Up
    • 'escape' - user pressed Escape
    • 'enter' - user pressed Enter
    • 'click' - user clicked (or tapped) on suggestion
    • 'type' - none of the methods above (usually means that user typed something, but can also be that they pressed Backspace, pasted something into the input, etc.)

inputProps.onBlur (optional)

The signature is:

function onBlur(event, { highlightedSuggestion })

where:

  • highlightedSuggestion - the suggestion that was highlighted just before the input lost focus, or null if there was no highlighted suggestion.

containerProps

Provides arbitrary properties to the outer div container of Autosuggest. Allows the override of accessibility properties.

const containerProps = {
  dataId: 'my-data-id'
  // ... any other properties
};

onSuggestionSelected (optional)

This function is called when suggestion is selected. It has the following signature:

function onSuggestionSelected(event, { suggestion, suggestionValue, suggestionIndex, sectionIndex, method })

where:

  • suggestion - the selected suggestion
  • suggestionValue - the value of the selected suggestion (equivalent to getSuggestionValue(suggestion))
  • suggestionIndex - the index of the selected suggestion in the suggestions array
  • sectionIndex - when rendering multiple sections, this will be the section index (in suggestions) of the selected suggestion. Otherwise, it will be null.
  • method - string describing how user selected the suggestion. The possible values are:
    • 'click' - user clicked (or tapped) on the suggestion
    • 'enter' - user selected the suggestion using Enter

onSuggestionHighlighted (optional)

This function is called when the highlighted suggestion changes. It has the following signature:

function onSuggestionHighlighted({ suggestion })

where:

  • suggestion - the highlighted suggestion, or null if there is no highlighted suggestion.

shouldRenderSuggestions (optional)

By default, suggestions are rendered when the input isn't blank. Feel free to override this behaviour.

This function gets the current value of the input and the reason why the suggestions might be rendered, and it should return a boolean.

For example, to display suggestions only when input value is at least 3 characters long, do:

function shouldRenderSuggestions(value, reason) {
  return value.trim().length > 2;
}

You can use the second reason argument to finely control exactly when the suggestions are rendered. The possible values are closely related to those for onSuggestionsFetchRequested, plus a few extra cases:

  • 'input-changed' - user typed something
  • 'input-focused' - input was focused
  • 'input-blurred' - input was un-focused
  • 'escape-pressed' - user pressed Escape to clear the input (and suggestions are shown for empty input)
  • 'suggestions-revealed' - user pressed Up or Down to reveal suggestions
  • 'suggestions-updated' - the suggestions were updated
  • 'render' - the component is re-rendering

When shouldRenderSuggestions returns true, suggestions will be rendered only when the input is focused.

If you would like to render suggestions regardless of whether the input is focused or not, set alwaysRenderSuggestions={true} (shouldRenderSuggestions is ignored in this case).

alwaysRenderSuggestions (optional)

Set alwaysRenderSuggestions={true} if you'd like to always render the suggestions.

Important: Make sure that the initial value of suggestions corresponds to the initial value of inputProps.value. For example, if you'd like to show all the suggestions when the input is empty, your initial state should be something like:

this.state = {
  value: "",
  suggestions: allSuggestions
};

highlightFirstSuggestion (optional)

When highlightFirstSuggestion={true}, Autosuggest will automatically highlight the first suggestion. Defaults to false.

focusInputOnSuggestionClick (optional)

By default, focusInputOnSuggestionClick={true}, which means that, every time suggestion is clicked (or tapped), the input keeps the focus.

On mobile devices, when the input is focused, the native keyboard appears. You'll probably want to lose the focus when suggestion is tapped in order to hide the keyboard.

You can do something like this:

<Autosuggest focusInputOnSuggestionClick={!isMobile} ... />

where isMobile is a boolean describing whether Autosuggest operates on a mobile device or not. You can use kaimallea/isMobile, for example, to determine that.

multiSection (optional)

By default, Autosuggest renders a plain list of suggestions.

If you'd like to have multiple sections (with optional titles), set multiSection={true}.

renderSectionTitle (required when multiSection={true})

When rendering multiple sections, you need to tell Autosuggest how to render a section title.

This function gets the section to render (an item in the suggestions array), and it should return a string or a ReactElement. For example:

function renderSectionTitle(section) {
  return <strong>{section.title}</strong>;
}

If renderSectionTitle returns null or undefined, section title is not rendered.

getSectionSuggestions (required when multiSection={true})

When rendering multiple sections, you need to tell Autosuggest where to find the suggestions for a given section.

This function gets the section to render (an item in the suggestions array), and it should return an array of suggestions to render in the given section. For example:

function getSectionSuggestions(section) {
  return section.suggestions;
}

Note: Sections with no suggestions are not rendered.

renderInputComponent (optional)

You shouldn't specify renderInputComponent unless you want to customize the rendering of the input.

To keep Autosuggest accessible, renderInputComponent MUST:

  • render an input
  • pass through all the provided inputProps to the input

Example:

const renderInputComponent = inputProps => (
  <div>
    <input {...inputProps} />
    <div>custom stuff</div>
  </div>
);

Note: When using renderInputComponent, you still need to specify the usual inputProps. Autosuggest will merge the inputProps that you provide with other props that are needed for accessibility (e.g. 'aria-activedescendant'), and will pass the merged inputProps to renderInputComponent.

renderSuggestionsContainer (optional)

You shouldn't specify renderSuggestionsContainer unless you want to customize the content or behaviour of the suggestions container beyond rendering the suggestions themselves. For example, you might want to add a custom text before/after the suggestions list, or to customize the scrolling behaviour of the suggestions container.

The signature is:

function renderSuggestionsContainer({ containerProps, children, query })

where:

  • containerProps - props that you MUST pass to the topmost element that is returned from renderSuggestionsContainer.
  • children - the suggestions themselves. It's up to you where to render them.
  • query - Same as query in renderSuggestion.

For example:

function renderSuggestionsContainer({ containerProps, children, query }) {
  return (
    <div {...containerProps}>
      {children}
      <div>
        Press Enter to search <strong>{query}</strong>
      </div>
    </div>
  );
}

When renderSuggestionsContainer returns a composite component (e.g. <IsolatedScroll ... /> as opposed to a DOM node like <div ... />), you MUST call containerProps.ref with the topmost element that the composite component renders.

For example:

import IsolatedScroll from "react-isolated-scroll";

function renderSuggestionsContainer({ containerProps, children }) {
  const { ref, ...restContainerProps } = containerProps;
  const callRef = isolatedScroll => {
    if (isolatedScroll !== null) {
      ref(isolatedScroll.component);
    }
  };

  return (
    <IsolatedScroll ref={callRef} {...restContainerProps}>
      {children}
    </IsolatedScroll>
  );
}

theme (optional)

Autosuggest comes with no styles.

It uses react-themeable that allows you to style your Autosuggest component using CSS Modules, Radium, Aphrodite, JSS, Inline styles, and global CSS.

For example, to style the Autosuggest using CSS Modules, do:

/* theme.css */

.container { ... }
.input { ... }
.suggestionsContainer { ... }
.suggestion { ... }
.suggestionHighlighted { ... }
...
import theme from "theme.css";
<Autosuggest theme={theme} ... />

When not specified, theme defaults to:

{
  container:                'react-autosuggest__container',
  containerOpen:            'react-autosuggest__container--open',
  input:                    'react-autosuggest__input',
  inputOpen:                'react-autosuggest__input--open',
  inputFocused:             'react-autosuggest__input--focused',
  suggestionsContainer:     'react-autosuggest__suggestions-container',
  suggestionsContainerOpen: 'react-autosuggest__suggestions-container--open',
  suggestionsList:          'react-autosuggest__suggestions-list',
  suggestion:               'react-autosuggest__suggestion',
  suggestionFirst:          'react-autosuggest__suggestion--first',
  suggestionHighlighted:    'react-autosuggest__suggestion--highlighted',
  sectionContainer:         'react-autosuggest__section-container',
  sectionContainerFirst:    'react-autosuggest__section-container--first',
  sectionTitle:             'react-autosuggest__section-title'
}

The following picture illustrates how theme keys correspond to Autosuggest DOM structure:

DOM structure

id (required when multiple Autosuggest components are rendered on a page)

The only reason id exists, is to set ARIA attributes (they require a unique id).

When rendering a single Autosuggest, don't set the id (it will be set to '1', by default).

When rendering multiple Autosuggest components on a page, make sure to give them unique ids. For example:

<Autosuggest id="source" ... />
<Autosuggest id="destination" ... />

Development

npm install
npm start

Now, open http://localhost:3000/demo/dist/index.html and start hacking!

License

MIT