I have a list, build with material-ui. There are a lot of items in it, so scrollbar is visible.
What I would like to do is scroll to the selected item. Have any ideas of how to implement this?
Here is a demo sendbox link
After click on the item list should looks like this (selected item is in the center):
I have a list, build with material-ui. There are a lot of items in it, so scrollbar is visible.
What I would like to do is scroll to the selected item. Have any ideas of how to implement this?
Here is a demo sendbox link
After click on the item list should looks like this (selected item is in the center):
Share Improve this question asked Sep 30, 2019 at 14:28 SergeySergey 1,0754 gold badges15 silver badges33 bronze badges3 Answers
Reset to default 14I know there is an accepted answer here, but I think using
<ListItem autoFocus={true}/>
would scroll that list item into view. The same logic to set the list item to be marked as selected could be used for setting the autoFocus
attribute as well.
Chandra Hasa's answer should include a bit of extra explanation but the edit queue was full.
Material-ui has a built-in way to do this with the autoFocus
prop. See the table below taken from the MUI Docs.
Prop | Type | Default | Description |
---|---|---|---|
autoFocus | boolean | false | If true, the list item is focused during the first mount. Focus will also be triggered if the value changes from false to true. |
❗️ The autoFocus
prop should only be true
for one item in the list. If you add autoFocus={true}
to every ListItem
, it will continuously scroll to each element, like OP mentioned in his comment.
The browser will scroll to the one ListItem
that has autoFocus={true}
.
If you want to always scroll to the same ListItem
every time the component renders, you can add autoFocus={true}
to that one ListItem
component, like this:
<List>
<ListItem>item1</ListItem>
<ListItem autoFocus={true}>The list will automatically scroll to this item</ListItem>
<ListItem>item3</ListItem>
</List>
In most cases, people want to dynamically determine which ListItem
to scroll to. In this case, the value of the autoFocus
prop needs to evaluate to a boolean
. It should still only be true
for one item in the list.
One use case is if you're rendering a long list with one option already selected. It's good to automatically scroll so the selected option is visible.
/* The list will auto-scroll to the **one** item that has an
`autoFocus` prop that evaluates to `true`.
If `selectedItem === item2`,
the list will automatically scroll to `item2`.
*/
<List>
<ListItem autoFocus={ selectedItem === item1 }> item1 </ListItem>
<ListItem autoFocus={ selectedItem === item2 }> item2 </ListItem>
<ListItem autoFocus={ selectedItem === item3 }> item3 </ListItem>
</List>
❗️ This question and answers use MUI v4. MUI v5 deprecated the autoFocus
prop for ListItem
components. Use ListItemButton
instead. It still has the autoFocus
prop and works as described above. Don't worry, it doesn't look like an MUI Button
component.
Deprecated - checkout ListItemButton instead (Source: MUI Docs)
Hold a ref to the List, and upon click on ListItem, calculate how much you need to scroll based on:
- list item height
- the index of the selected item
number of visible list items.
const scrollableListRef = React.createRef(); function Row(props) { const { index, style } = props; const placeSelectedItemInTheMiddle = (index) => { const LIST_ITEM_HEIGHT = 46; const NUM_OF_VISIBLE_LIST_ITEMS = 9; const amountToScroll = LIST_ITEM_HEIGHT * (index - (NUM_OF_VISIBLE_LIST_ITEMS / 2) + 1) ; scrollableListRef.current.scrollTo(amountToScroll, 0); } return ( <ListItem button style={style} key={index} onClick={() => {placeSelectedItemInTheMiddle(index)}}> <ListItemText primary={`Item ${index + 1}`} /> </ListItem> ); }