diff --git a/README.md b/README.md
index 222fe13f6..6b341b70c 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ harder to contribute to.
- [Control Props](#control-props)
- [Child Callback Function](#child-callback-function)
- [Examples](#examples)
+- [FAQ](#faq)
- [Inspiration](#inspiration)
- [Other Solutions](#other-solutions)
- [Contributors](#contributors)
@@ -287,6 +288,14 @@ The currently selected item.
This is called with an object. Read more about the properties of this object
in the section "Child Callback Function"
+### id
+
+> `string` | defaults to a generated ID
+
+You should not normally need to set this prop. It's only useful if you're
+server rendering items (which each have an `id` prop generated based on the
+`downshift` `id`). For more information see the `FAQ` below.
+
## Control Props
downshift manages its own state internally and calls your `onChange` and
@@ -517,6 +526,36 @@ You'll find other examples in the `stories/examples` folder of the repo.
And you'll find
[a live version of those examples here](https://downshift.netlify.com)
+## FAQ
+
+
+
+How do I avoid the checksum error when server rendering (SSR)?
+
+The checksum error you're seeing is most likely due to the automatically
+generated `id` and/or `htmlFor` prop you get from `getInputProps` and
+`getLabelProps` (respectively). It could also be from the automatically
+generated `id` prop you get from `getItemProps` (though this is not likely as
+you're probably not rendering any items when rendering a downshift component
+on the server).
+
+To avoid these problems, simply provide your own `id` prop in `getInputProps`
+and `getLabelProps`. Also, you can use the `id` prop on the component
+`Downshift`. For example:
+
+```javascript
+
+ {({getInputProps, getLabelProps}) => (
+
+
+ )}
+
+```
+
+
+
## Inspiration
diff --git a/src/__tests__/downshift.misc.js b/src/__tests__/downshift.misc.js
index a7adfeab0..736cccbd8 100644
--- a/src/__tests__/downshift.misc.js
+++ b/src/__tests__/downshift.misc.js
@@ -96,6 +96,12 @@ test('openAndHighlightDefaultIndex can take no arguments at all', () => {
)
})
+test('can specify a custom ID which is used in item IDs (good for SSR)', () => {
+ const id = 'my-custom-id'
+ const {getItemProps} = setup({id})
+ expect(getItemProps({item: 'blah'}).id).toContain(id)
+})
+
function setup({children = () =>
, ...props} = {}) {
let renderArg
const childSpy = jest.fn(controllerArg => {
diff --git a/src/downshift.js b/src/downshift.js
index 2ee341460..b573f6424 100644
--- a/src/downshift.js
+++ b/src/downshift.js
@@ -33,6 +33,7 @@ class Downshift extends Component {
onUserAction: PropTypes.func,
onClick: PropTypes.func,
itemCount: PropTypes.number,
+ id: PropTypes.string,
// things we keep in state for uncontrolled components
// but can accept as props for controlled components
/* eslint-disable react/no-unused-prop-types */
@@ -49,6 +50,7 @@ class Downshift extends Component {
defaultInputValue: '',
defaultIsOpen: false,
getA11yStatusMessage,
+ id: generateId('downshift'),
itemToString: i => (i == null ? '' : String(i)),
onStateChange: () => {},
onUserAction: () => {},
@@ -93,7 +95,6 @@ class Downshift extends Component {
this.state = state
}
- id = generateId('downshift')
root_handleClick = composeEventHandlers(
this.props.onClick,
this.root_handleClick,
@@ -543,7 +544,7 @@ class Downshift extends Component {
/////////////////////////////// ITEM
getItemId(index) {
- return `${this.id}-item-${index}`
+ return `${this.props.id}-item-${index}`
}
getItemProps = (