React-select: Scrolling with arrow keys on custom option does not change view

Created on 28 Aug 2018  路  16Comments  路  Source: JedWatson/react-select

I have created a custom Option renderer for an async dropdown and have spread the innerProps as the docs instruct, however when scrolling through the option items with the arrow keys, the view does not update despite the focused option item changing.

Please see sandbox here: https://codesandbox.io/s/x90v3pkkzp

Once you open the dropdown menu you and scroll through with the arrow keys that the focus changes however the view stays on the first five listed options.

issubug-unconfirmed issureviewed

Most helpful comment

@vitalybe @rhansen-carecloud @nlokare
Try wrapping your CustomOption with components.Option.
https://codesandbox.io/s/8kyp183z99

All 16 comments

@rhansen-carecloud What do you mean by "the view does not update?" If you keep pressing the down arrow key, the menu scrolls down.

@sahibjotsaggu if you check my sandbox, I am passing in a custom option component that renders the color options. Once you click on the input, toggling open the menu list, and use the arrow keys to scroll down, the menu does not scroll. When using the arrow keys you can see that the focused option is changing via the console log, but the menu is not scrolling with it.

I'm experiencing the same issue with custom Option component. I've forked @rhansen-carecloud example to make it a bit clearer:

https://codesandbox.io/s/1qx791llp7

Note that as you press down the yellow selection works as expected, but once it reaches the edge it simply disappears and the window doesn't scroll...

@rhansen-carecloud I've made a quick fix to use in the meantime, it is a bit of a hack and could use some optimization... But it works:

https://codesandbox.io/s/714qqlwv36

@vitalybe I implemented your example but it looks like when your scroll with the mouse, the menu jumps back to the top until you reach the end of the list. I wonder if the componentDidUpdate logic is breaking the mouse scroll.

@vitalybe @rhansen-carecloud @nlokare
Try wrapping your CustomOption with components.Option.
https://codesandbox.io/s/8kyp183z99

I have the same issue but with a Custom MenuList component.
https://codesandbox.io/s/84ry9k8910
Even if I wrap the List inside components.MenuList, I still can't scroll.

@AzaeI You can use the scrollToIndex prop. Each child (Option) has an isFocused attribute. Just scroll to the index of the last child in focus:
https://codesandbox.io/s/3yzz57lmo5

There are performance issues on long lists though: https://github.com/JedWatson/react-select/issues/2850

I had the same issue as OP and tried many things suggested in different articles. These were some of my most useful/relevant references;

I ended up using a small part of react-window-select to find the "focused" item in my passed props and use the List "scrollToIndex" api to scroll to it. Here's my full code example;

import React from 'react';
import {FixedSizeList as List} from 'react-window';

const height = 40;
export class MenuList extends React.Component {
    constructor(props) {
        super(props);
        this.listRef = undefined;
    }

  getFocusIndex = children => {
        const isArray = children instanceof Array;
        children = isArray ? children : [children];
        return Math.max(
            children.findIndex(({props: {isFocused} = {}} = {}) => {
                return isFocused === true;
            }),
            0,
        );
    };

    componentDidUpdate(prevProps, prevState) {
        if (this.props.children.length === 1) {
            this.listRef.resetAfterIndex(0);
        }

        /**
         * enables scrolling on key down arrow
         *
         * note: prevents scrolling on index 0 and 1 to avoid
         * returning to top of menu when it remains open after selecting
         */
        const currentIndex = this.getFocusIndex(this.props.children);
        if (currentIndex > 1) {
            this.listRef.scrollToItem(currentIndex);
        }
    }

    render() {
        const {children, maxHeight} = this.props;

        return (
            <List
                ref={ref => {
                    this.listRef = ref;
                }}
                height={Math.min(maxHeight, (children.length || 1) * height)}
                itemCount={children.length}
                itemSize={height}
                overscanCount={5}
            >
                {({index, style}) => <div style={style}>{children[index]}</div>}
            </List>
        );
    }
}

the same problem facing .... Just removed backgroundColor & Color property from custom option component so array key down and up working fine...
But I have to implement these properties to change color

I don't know what to do....

@JedWatson

I had the same issue as OP and tried many things suggested in different articles. These were some of my most useful/relevant references;

I ended up using a small part of react-window-select to find the "focused" item in my passed props and use the List "scrollToIndex" api to scroll to it. Here's my full code example;

import React from 'react';
import {FixedSizeList as List} from 'react-window';

const height = 40;
export class MenuList extends React.Component {
    constructor(props) {
        super(props);
        this.listRef = undefined;
    }

  getFocusIndex = children => {
        const isArray = children instanceof Array;
        children = isArray ? children : [children];
        return Math.max(
            children.findIndex(({props: {isFocused} = {}} = {}) => {
                return isFocused === true;
            }),
            0,
        );
    };

    componentDidUpdate(prevProps, prevState) {
        if (this.props.children.length === 1) {
            this.listRef.resetAfterIndex(0);
        }

        /**
         * enables scrolling on key down arrow
         *
         * note: prevents scrolling on index 0 and 1 to avoid
         * returning to top of menu when it remains open after selecting
         */
        const currentIndex = this.getFocusIndex(this.props.children);
        if (currentIndex > 1) {
            this.listRef.scrollToItem(currentIndex);
        }
    }

    render() {
        const {children, maxHeight} = this.props;

        return (
            <List
                ref={ref => {
                    this.listRef = ref;
                }}
                height={Math.min(maxHeight, (children.length || 1) * height)}
                itemCount={children.length}
                itemSize={height}
                overscanCount={5}
            >
                {({index, style}) => <div style={style}>{children[index]}</div>}
            </List>
        );
    }
}

I tried to use this solution.. but my select has infinite scrolling, and when I'm pressing arrow down to load more items when at the bottom, the currentIndex bugs out. Do you know a solution for it? Btw, thank you for presenting your solution!

@aakhan89 In your case, seems like you're only checking for state.isSelected to set your options background. You might want to also look at state.isFocused which is set to true on the current option when navigating with the arrow keys.

This works for me:
image

I've started a fork of react-select. Feel free to resubmit this issue on the fork and/or submit a PR to resolve this issue on the fork and we can get it merged and released.

Greetings,

@rhansen-carecloud and others...

I verified that the specified behavior was consistent in the codesandbox provided.

However, I noticed that the provided example was using v2.0.0-7-beta, so I forked that codesandbox and updated to the most recent V2 (2.4.4) and V3 (3.1.1) versions of react-select. In my tests with each, I was able to verify that the scrolling worked without issue and the buggy scroll behavior (or at least lack thereof) was no longer present.

Here is the V2 sandbox.

I will be closing out this issue, based on the provided findings.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pashap picture pashap  路  3Comments

pablote picture pablote  路  3Comments

AchinthaReemal picture AchinthaReemal  路  3Comments

mbonaci picture mbonaci  路  3Comments

coder-guy22296 picture coder-guy22296  路  3Comments