react-native: [PickerIOS] Wrapping `PickerIOS` with a container and `flexDirection: "row"` view breaks scrolling and selection

Wrapping a PickerIOS with a parent who has the styles flex: 1, flexDirection: "row" breaks PickerIOS views completely. It doesn’t break date picker views, though.

Example code (the bottom picker will be unselectable):

/**
 * The examples provided by Facebook are for non-commercial testing and
 * evaluation purposes only.
 *
 * Facebook reserves all rights not expressly granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
 * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 * @flow
 */
'use strict';

var React = require('react-native');

var {
  PickerIOS,
  Text,
  View,
} = React;

var PickerItemIOS = PickerIOS.Item;

var CAR_MAKES_AND_MODELS = {
  amc: {
    name: 'AMC',
    models: ['AMX', 'Concord', 'Eagle', 'Gremlin', 'Matador', 'Pacer'],
  },
  alfa: {
    name: 'Alfa-Romeo',
    models: ['159', '4C', 'Alfasud', 'Brera', 'GTV6', 'Giulia', 'MiTo', 'Spider'],
  },
  aston: {
    name: 'Aston Martin',
    models: ['DB5', 'DB9', 'DBS', 'Rapide', 'Vanquish', 'Vantage'],
  },
  audi: {
    name: 'Audi',
    models: ['90', '4000', '5000', 'A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'Q5', 'Q7'],
  },
  austin: {
    name: 'Austin',
    models: ['America', 'Maestro', 'Maxi', 'Mini', 'Montego', 'Princess'],
  },
  borgward: {
    name: 'Borgward',
    models: ['Hansa', 'Isabella', 'P100'],
  },
  buick: {
    name: 'Buick',
    models: ['Electra', 'LaCrosse', 'LeSabre', 'Park Avenue', 'Regal',
             'Roadmaster', 'Skylark'],
  },
  cadillac: {
    name: 'Cadillac',
    models: ['Catera', 'Cimarron', 'Eldorado', 'Fleetwood', 'Sedan de Ville'],
  },
  chevrolet: {
    name: 'Chevrolet',
    models: ['Astro', 'Aveo', 'Bel Air', 'Captiva', 'Cavalier', 'Chevelle',
             'Corvair', 'Corvette', 'Cruze', 'Nova', 'SS', 'Vega', 'Volt'],
  },
};

var PickerExample = React.createClass({
  getInitialState: function() {
    return {
      carMake: 'cadillac',
      modelIndex: 3,
    };
  },

  render: function() {
    var make = CAR_MAKES_AND_MODELS[this.state.carMake];
    var selectionString = make.name + ' ' + make.models[this.state.modelIndex];
    debugger;
    return (
      <View>
        <Text>Please choose a make for your car:</Text>
        <PickerIOS
          selectedValue={this.state.carMake}
          onValueChange={(carMake) => this.setState({carMake, modelIndex: 0})}>
          {Object.keys(CAR_MAKES_AND_MODELS).map((carMake) => (
            <PickerItemIOS
              key={carMake}
              value={carMake}
              label={CAR_MAKES_AND_MODELS[carMake].name}
              />
            )
          )}
        </PickerIOS>

        <Text>Please choose a model of {make.name}:</Text>
        <View style={{flex: 1, flexDirection: 'row'}}>
            <PickerIOS
              selectedValue={this.state.modelIndex}
              key={this.state.carMake}
              onValueChange={(modelIndex) => this.setState({modelIndex})}>
              {CAR_MAKES_AND_MODELS[this.state.carMake].models.map(
                (modelName, modelIndex) => (
                  <PickerItemIOS
                    key={this.state.carmake + '_' + modelIndex}
                    value={modelIndex}
                    label={modelName}
                  />
                ))
              }
            </PickerIOS>
        </View>
        <Text>You selected: {selectionString}</Text>
      </View>
    );
  },
});
module.exports = PickerExample;

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 15 (11 by maintainers)

Most upvoted comments

So one of the easy solutions is, in PickerIOS.js, wrapping RCTPicker in a view like so:

  render: function() {
    return (
      <View style={this.props.style}>
        <View style={{flex: 1, flexDirection: 'column'}}>
          <RCTPickerIOS
            ref={PICKER}
            style={styles.pickerIOS}
            items={this.state.items}
            selectedIndex={this.state.selectedIndex}
            onChange={this._onChange}
          />
        </View>
      </View>
    );
  },

It’s an unexpected wrapper and band-aid though. Just haven’t been able to pinpoint the relationship between flexbox and the RCTPicker view to figure out the issue.