This library now relies on hooks, both in the package itself as well as underlying dependencies. You must upgrade your version of React and ReactDOM to be at least 16.8
Among other things, this consists of updating the HTML structure and class names of included components like MenuItem
in a backwards-incompatible way. Note that if you are using BS3, things should still work, but you may need to render your own menu, menu item, and input components.
The getInstance
method was deprecated in v4.2.0 and has been removed. You can access instance methods on the ref
itself.
This should generally be a transparent change. There is at least one instance where it could break existing code, however: if your onSearch
handler is re-instantiated on each render, this will cancel the debounced function and potentially prevent onSearch
from being called. To avoid this, either bind the handler in the constructor or use class properties (if using a class component) or use useCallback
with a dependency array (if using a functional component):
// This may cause problems:
<AsyncTypeahead
...
onSearch={(query) => {
// Do stuff...
}}
/>
// Instead, do one of the following:
class MyComponent extends React.Component {
render () {
<AsyncTypeahead
...
onSearch={this.handleSearch}
/>
}
handleSearch = (query) => {
// Do stuff...
}
}
const MyComponent = () => {
const handleSearch = useCallback((query) => {
// Do stuff...
}, []);
return (
<AsyncTypeahead
...
onSearch={handleSearch}
/>
);
};
For more, see issue #561.
findDOMNode
was deprecated in React 16.3 and all uses of it (including dependencies) are now gone. In some cases, this now requires explicitly passing refs to underlying DOM nodes.
When using renderInput
, you will need to pass both the inputRef
and referenceElementRef
prop to a DOM node. This will usually be the input itself, but may be a container node:
<Typeahead
...
renderInput={({ inputRef, referenceElementRef, ...inputProps }) => (
<Form.Control
{...inputProps}
ref={(inputNode) => {
inputRef(inputNode);
referenceElementRef(inputNode);
}}
/>
)}
/>
When using custom tokens, you will need to pass the ref from withToken
to the token's DOM node:
const MyToken = withToken(forwardRef((props, ref) => (
<div
className="my-token"
ref={ref}>
{props.children}
</div>
)));
Rewriting the HOC as a component makes it a little easier to use and better reflects its relationship with the input.
import { Form } from 'react-bootstrap';
import { Typeahead, hintContainer } from 'react-bootstrap-typeahead';
const FormControlWithHint = hintContainer(Form.Control);
<Typeahead
...
renderInput={(...) => (
<FormControlWithHint {...} />
)}
/>
import { Form } from 'react-bootstrap';
import { Typeahead, Hint } from 'react-bootstrap-typeahead';
<Typeahead
...
renderInput={(...) => (
<Hint>
<Form.Control {...} />
</Hint>
)}
/>
The bsSize
prop was deprecated in v4.2.0 and has been removed. Use size
instead.
This change is only relevant if you are overriding the .rbt-input-multi
CSS class. It increases the CSS specificity for the input's height to make the styling less dependent on stylesheet ordering and thus less likely to break.
React and ReactDOM >=16.3 are now required as peer dependencies.
onMenuHide
andonMenuShow
were removed. UseonMenuToggle
instead.
tokenContainer
no longer uses findDOMNode
, and instead passes a ref
to the wrapped component. If you are using your own menu item component to render the menu, you must forward that ref to the underlying DOM node.
Pass option
as a prop to Token
(or tokenContainer
if using your own token markup) so the container can correctly handle the onRemove
callback.
<Typeahead
...
renderToken={(option, props, idx) => (
<Token
...
onRemove={props.onRemove}
option={option}>
{option.label}
</Token>
)}
/>
This behavior was a legacy workaround introduced before renderMenu
could return null
. That is no longer the case and renderMenu
should now be used to achieve the behavior:
<Typeahead
...
renderMenu={(results, menuProps) => {
if (!results.length) {
return null;
}
return <TypeaheadMenu {...menuProps} />;
}}
/>
The menuId
prop has been replaced by id
and no longer provides a default value. You must provide an id for assistive technologies like screen readers.
Behavior is now correct according to a11y standards, but may result in unexpected behaviors since different browsers handle this attribute differently.
- To keep the previous behavior, pass "nope" value in
inputProps
.
Overlay was updated to take advantage of Popper.js' fixed positioning rather than using a portal to attach the menu to the document body. This greatly simplifies the component and gives greater control over styling.
bodyContainer
props was removed. UsepositionFixed
instead.- Use of
.rbt-body-container
for CSS scoping will no longer work. Pass your own scoping classnames to the component instead.
This piece of functionality is not part of the WAI-ARIA authoring guidelines and was difficult to test and support.
a11yNumResults
&a11yNumSelected
are now no-ops- If you need this functionality, you can add it yourself as a child (or child function) of the component.
- The
name
prop was deprecated in v2.0 and is now gone. - Non-string values for the
maxHeight
prop were deprecated in v2.5 and are now no longer allowed.
If you pass a callback to filterBy
, it will now receive the set of internal props as the second parameter instead of the user-input text
value:
// v2.0
<Typeahead
...
filterBy={(option, text) => {
// Your own filtering code goes here.
}}
/>
// v3.0
<Typeahead
...
filterBy={(option, props) => {
// Your own filtering code goes here.
// `text` is now `props.text`
}}
/>
Similarly, renderToken
now receives internal props as the second param rather than just the onRemove
function:
// v2.0
<Typeahead
...
multiple
renderToken={(option, onRemove, index) => {
// Your own token rendering code.
}}
/>
// v3.0
<Typeahead
...
multiple
renderToken={(option, props, index) => {
// Your own token rendering code.
// `onRemove` is now `props.onRemove`
}}
/>
This version includes some significant internal refactoring in an effort to provide better support for Bootstrap 4. If you have custom CSS that depends on internal (eg: rbt-*
) classnames, you should check to make sure things still work as you expect.
AsyncTypeahead
no longer trims whitespace on or lowercases queries. The original intent was to provide some basic normalization of queries, but this resulted in strange behaviors. You should now do any checking you want, like ignoring queries with only whitespace, in your onSearch
function.
The onChange
and onInputChange
callbacks were previously called in componentWillReceiveProps
, which triggered multiple calls and didn't emulate how a normal form element works. These change callbacks are now only triggered by user actions, eg: typing in the input, clicking on a menu item, etc. You may need to update your code if it relied on a change event being triggered due to prop changes.
Finally, if you use the renderMenu
prop, a couple changes were made that may affect you:
The typeahead now uses Popper.js (via react-popper
) for menu positioning. If you're using the provided Menu
component inside renderMenu
, simply pass down all the menu props and everything should work fine. If you're using your own component to render the menu, be sure it properly consumes the innerRef
prop that gets passed down or the component will not work correctly:
class MyCustomMenu extends React.Component {
render() {
// `innerRef` is passed down by the Popper...
const {innerRef, ...props} = this.props;
// ...and must be passed to the `ref` of your custom component.
return <div {...props} ref={innerRef} />;
}
}
To make the pagination menu item keyboard-accessible, it is no longer automatically included in the Menu
component. Instead, it is added to the result set, similar to the custom (allowNew
) item. That means you must now handle rendering of the pagination item yourself if you want pagination. See TypeaheadMenu
for an example of how to do this.
Version 2.0 consists mainly of internal refactoring aimed at reducing parallel code paths and making certain complex feature requests possible. These changes should mostly be transparent, though you may notice that the component behaves a bit differently.
The AsyncTypeahead
component now requires the request state to be managed externally. Use the isLoading
prop to tell the component if a request is pending or not. See the example for an illustration of proper usage.
In an effort to simplify the CSS and as a result of the refactor, class names for the various internal components were changed. This may cause styling to break if you relied on a certain naming scheme. The separate CSS files were also combined into a single file (Typeahead.css
) to make it easier to include.
- The
name
prop is now deprecated and will be removed in v3.0. UseinputProps
to apply props directly to the input instead.
Version 1.0 has a few breaking changes, but upgrading should be relatively painless.
The main change affecting all users is that the typeahead is now a property of the module:
// v0.10.x
import Typeahead from 'react-bootstrap-typeahead'; // ES2015
var Typeahead = require('react-bootstrap-typeahead').default; // CommonJS
// v1.x
import {Typeahead} from 'react-bootstrap-typeahead'; // ES2015
var Typeahead = require('react-bootstrap-typeahead').Typeahead; // CommonJS
This prop was deprecated in v0.9.0 and is now gone.
The signature for the renderMenuItemChildren
callback was changed such that the data item is now the first argument and props are second. This felt more logical and all such render
functions follow a similar pattern.
// v0.10.x
renderMenuItemChildren(props, result, index) {
// Rendering code here...
}
// v1.x
renderMenuItemChildren(result, props, index) {
// Rendering code here...
}
That should be everything. If you come across something I missed, please open an issue. Thanks!