React Native - How do I know which dynamic Component was pressed?

I'm new to React Native and am creating a screen with several Switches, the number and specifics of which aren't known until runtime.

In the onValueChange callback, the new value of the Switch is passed in, but how can I identify which Switch was actually pressed? (code simplified)

export default class Class1 extends Component
{
    switchhit(newval)
    {
        console.log('*How do I know which switch was hit?* newval=' + newval);
    }

    render()
    {
        let ii, arrC = [];

        for (ii = 0; ii < sSettChcs.length; ii++)
        {
            let jsx0 =
                <View>
                    <View>
                        <Text>{ sSettChcs[ii] }</Text>
                        <Text>{ sSettDesc[ii] }</Text>
                    </View>
                    <View>
                        <Switch 
                            onValueChange = { (newval) => this.switchhit(newval) }
                            value = { true } />
                    </View>
                </View>;
            arrC.push(jsx0);
        }

        let jsx =
            <ScrollView>{ arrC }</ScrollView>;
        return jsx;
    }
}

Note that this is a simplified example and the final screen will have Components of type TextInput, Picker, etc. so my question isn't really specific to just Switch.

2 answers

  • answered 2018-10-11 22:28 Roger

    With some help here I found that a straightforward way to do this is to "subclass" via composition your component (Switch in this case) and store an identifier (idx0 below):

    class MySwitch extends Component
    {
        swbang(newval)
        {
            console.log('newval=' + newval + 'idx0=' + this.props.idx0);
        }
    
        render()
        {
            return (
              <View>
                <Switch 
                    onValueChange = { (newval) => this.swbang(newval) }
                    value = { true } />
              </View>
            );
        }
    }
    

    The original code then becomes:

    export default class Class1 extends Component
    {
        render()
        {
            let ii, arrC = [];
    
            for (ii = 0; ii < sSettChcs.length; ii++)
            {
                let jsx0 =
                    <View>
                        <View>
                            <Text>{ sSettChcs[ii] }</Text>
                            <Text>{ sSettDesc[ii] }</Text>
                        </View>
                        <View>
                            <MySwitch idx0 = { ii } />
                        </View>
                    </View>;
                arrC.push(jsx0);
            }
    
            let jsx =
                <ScrollView>{ arrC }</ScrollView>;
            return jsx;
        }
    }
    

    Simple in retrospect but nonintuitive coming from a Java/C type world.

    I'm sure this can be done better and that certain aspects don't conform to React Native style, but this demonstrates the concept.

  • answered 2018-10-11 22:28 Kapobajza

    A possible solution (but I don't think that it's the best one), would be to initialize an array of values which contain some sort of a unique id in the componentDidMount method:

    componentDidMount() {
      const data = [];
    
      // You'll probably need to set this sSettChcs array in the state
      for (i = 0; i < sSettChcs.length; i++) {
        data.push({ id: i, value: false });
      }
    
      this.setState({ data });
    }
    

    And then rewrite your switchint function to look something like this:

    switchhit(newval, id)
    {
        const newData = [];
    
        this.state.data.forEach(val => { 
          if (val.id === id) {
            newData.push({ id, value: newval });
          } else {
            newData.push(val);
          }
        });
    
        this.setState({ data: newData });
    }
    

    And then, in render:

    for (ii = 0; ii < this.state.data.length; ii++)
        {
            let jsx0 =
                <View>
                    <View>
                        <Text>{ sSettChcs[ii] }</Text>
                        <Text>{ sSettDesc[ii] }</Text>
                    </View>
                    <View>
                        <Switch 
                            onValueChange = { (newval) => this.switchhit(newval, this.state.data[ii].id) }
                            value = { this.state.data[ii].value } />
                    </View>
                </View>;
            arrC.push(jsx0);
        }