Generating variables dynamically within a React Native component

In my React Native component, I need to create a variable that will be used multiple times. Each instance of this component should have a different variable name for reference.

<View ref={view => { shapeView = view; }}   
        onLayout={({ nativeEvent }) => { 
            shapeView.measure((x, y, width, height, pageX, pageY) => {
            console.log('- - - DEBUG: width:' + width + ', pageX:'+ pageX + ', pageY:' + pageY);
            let shapePickerPosition = {w: width, x: pageX, y: pageY};
            setShapeCoords(shapePickerPosition);
            })
        }}>

Using this code within the component multiple times requires changing the variable name "shapeView" to avoid getting coordinates from only the last instance of the component.

Below is the complete component:


import React, {useState, useEffect} from 'react';
import {StyleSheet, View, Text, Modal, TouchableOpacity, Pressable, FlatList} from 'react-native';
import { useTheme } from '@react-navigation/native';

// ------------------PickerRow-----------------------------------------------------------------------
function CustomPickerRow(props) {

  const { colors } = useTheme(); // works
  const theme = useTheme();
  const [selectedItem, setSelectedItem] = useState('choose');
  const [coordinates, setCoordinates] = useState();

  const setItem = (value) => {
      // Set parent state
      props.action(value)
  }

    return (
      <View
        ref = { view => { shapeView  = view; } }
        onLayout={({ nativeEvent }) => {
            shapeView.measure( (x, y, width, height, pageX, pageY) => {
                console.log('height:', height);
                console.log('width:', width);
                console.log('x:', pageX);
                console.log('y:', pageY);
                let coords = {w: width, x: pageX, y: pageY};
                setCoordinates(coords);
              })

        }} 
        style = {{
        flexDirection: 'row', 
        justifyContent: 'space-between', 
        alignItems: 'center', 
        height: 25, 
        paddingLeft: 5, 
        marginBottom: 3, 
        backgroundColor: colors.frameBackground, 
        borderColor: colors.borderColor, 
        borderWidth: 1, 
        borderRadius: 5}}>
          <View style = {styles.icon}>
              <Text style = {styles.text}>{props.icon}</Text>
          </View>
          <View style = {styles.description}>
              <Text style = {{fontSize: 11, fontWeight: 'bold', color: colors.text, textAlign: 'left', marginLeft: 5}}>{props.title}</Text>
          </View>
          <MyPicker data={props.data} action={setItem} position={coordinates}/>
      </View>


    );
    }


  // ------------------MyPicker-----------------------------------------------------------------------
  function MyPicker(props) {

    const { colors } = useTheme(); // works
    const theme = useTheme();
    const [isVisible, setIsVisible] = useState(false);
    const [selectedItem, setSelectedItem] = useState(props.data[0].key)
    const [coordinates, setCoordinates] = useState({w: 180, x: 0, y: 0});

    useEffect(() => {
        if (props.position) {
            setCoordinates(props.position);
        }

    })

    const setItem = item => {
      // Set parent state
      props.action(item.value);
      setIsVisible(false);
      console.log("Chosen value = " + item.key);
      setSelectedItem(item.key);
    }

    const showPicker = () => {
        setIsVisible(true);
    }

    const renderItem = ({item}) => {
        return <View>
                    <Pressable onPress={() => setItem(item)}>
                        <Text style={{color: colors.text, fontSize: 17, alignSelf: 'center', paddingTop: 3}}>
                            {item.key}
                        </Text>
                    </Pressable>
                </View>
      }

      return (
        <View style={{flex:5, backgroundColor: 'transparent'}}>
            <TouchableOpacity onPress={showPicker}>
                <Text style={{color: colors.textSubtitleColor, fontSize: 11, alignSelf: 'flex-end', paddingRight: 10}}>
                      {selectedItem}
                </Text>
            </TouchableOpacity>

            <Modal animationType="fade"
                transparent={true}
                visible={isVisible}
                style={styles.testPicker}
                onRequestClose={() => {
                    console.log('Modal has been closed.');
                }}
                 >
                     <View style={{  backgroundColor: colors.frameBackground,
                                     borderColor: colors.borderColor, 
                                     borderWidth: 1, 
                                     borderRadius: 5,
                                     position: 'absolute',
                                     width:  180,
                                     height: 200,
                                     left: coordinates.x, 
                                     top: coordinates.y 
                                     }}>
                         <FlatList
                             data={props.data}
                             renderItem={renderItem}
                         />
                     </View>
             </Modal>
         </View>
      );
    }


    const styles = StyleSheet.create({

    testPicker: {
        backgroundColor: 'gray',
        position: 'absolute',
        width: 112,
        height: 200,
        left: 100,
        top: 160
      },
    icon: {
        flex: 1,
        backgroundColor: '#00529F', 
        marginRight: 0, 
        borderRadius: 5
    },
    description: {
        flex: 2,
        height: 17,
        backgroundColor: 'transparent', 
        marginRight: 0, 
        borderRadius: 5
    },

  });

  export default CustomPickerRow;

To invoke the component:

<CustomPickerRow id='shapePicker' icon='2' title='Shape:' data={shapeItems} action={setShape} selectedItem={selectedShape} visible={modalVisible} />

Answer №1

shapeView should be declared as a ref in the following way:

const MyComponent = () => {
   const shapeView = useRef();

   return (
     <View
       ref={view => shapeView.current = view}
       /* alternatively, it can be declared like this: ref={shapeView} */
       onLayout={({nativeEvent}) => {
          shapeView.current.measure(...);
       }
     />
   )
}

It is NOT RECOMMENDED to declare it like this:

let shapeView; // this declaration is outside of your component which is not ideal
const MyComponent = () => {

   return (
     <View
       ref={view => shapeView = view}
       onLayout={({nativeEvent}) => {
          shapeView.measure(...);
       }
     />
   )
}

If you are using a class based component, you can declare it in this manner:


class MyComponent extends React.Component {

    constructor() {
       this.shapeView = React.createRef();
    }

    render() {
       return (
         <View
           ref={this.shapeView}
           onLayout={({nativeEvent}) => {
              this.shapeView.current.measure(...);
           }
         />
       )
    }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Expanding your JavaScript skills: Tackling nested object key and value replacements

I am looking to manipulate the values of a nested object using JavaScript. The structure of the object is outlined below. let jsonObj = { "service":[ { "name":"restservice", "device&quo ...

Can you explain the purpose of the equals sign in ngRepeat?

Can you explain the significance of the equals sign in the ng-repeat attribute value? <li ng-repeat="person in people = (people | orderBy: firstname)"> rather than using: <li ng-repeat="person in people | orderBy: firstname"> I coul ...

Show real-time server responses using jQuery while waiting for the AJAX request to complete

I have a challenge in creating a function that displays the server response while waiting for Ajax to complete. Here's the scenario: I have selected 10 checkboxes. When I click the submit button, Ajax is triggered. On the server side, there is a loo ...

The console.log() displays the dictionary correctly, but trying to access it with a key results in it being undefined

I'm currently facing an issue with accessing the dictionary stored in the "workload" field of a document in Firestore. Here is the snippet of code I am struggling with: async addTask() { const projectDoc = await getDoc(doc(db, "projects", "Testing ...

Access PHP variables in JavaScript

In my project, I have a file named english.php which holds various variable values stored in the $LANG array. For example: $LANG['value_1']="abc"; $LANG['value_2']="xyz"; In addition to numerous .php files that include require_once( ...

Using React to implement MUI autocomplete feature alongside a MUI form

Recently, I have been utilizing a MUI form structured in the following manner: <Box component="form" onSubmit={event => { return handleSubmit(event); }} noValidate sx={{mt: 1}}> <TextField margin="normal" ...

Is there a way to determine where a Javascript event originated from when it was triggered programmatically?

In my current debugging situation, I am investigating why pressing Enter on a submit button triggers a 'click' event on that same button. It appears that the click event is being fired programmatically, which is the expected behavior in the appli ...

Place an element in relation to the vertical size of a div that includes written content

Currently, I am working on implementing a button with a popup that appears underneath it when the user hovers over it. The specific requirements for this setup are: The size of the button should not affect the size of the popup The popup should always be ...

My function is named, however, the output is recorded prior to the function completing its execution

I've implemented a function named createUser, designed to save user data in the database. If successful, it should return true; otherwise, false. The code for this function is as follows: exports.createUser = (user) => { const salt = crypto.rando ...

I am utilizing jQuery's AJAX function with a datatype of HTML to extract a specific portion of the incoming data

This is the JavaScript function I am working with: function getCountryRegions() { var postData = "id="+$("#selectedCountryId").val(); $.ajax({ url:"/region", data: postData, dataType:"html", type:"POST", ...

decoding json field containing forward slashes using javascript

Seems easy enough, but I'm having trouble figuring it out. let data="[{name:\"House\",id:\"1\"},{name:\"House and Land\",id:\"5\"},{name:\"Land\",id:\"6\"},{name:\"Terrace\",id:&bs ...

Exploring test suite pathways while utilizing ArcGIS JSAPI as an alternative loader within the Intern framework

I have been developing an application using the ArcGIS Javascript API and incorporating tests with Intern. While working on Windows 7 under IIS, I encountered some challenges but managed to overcome them by following the Intern tutorial and referring to so ...

AngularJS modal directives trigger a reset of $scope variables

I am developing a custom AngularJS application that needs to handle and store all the checkbox selections made by the user in a simple array of IDs. The functionality includes displaying a modal when the open button is clicked, allowing the user to perform ...

Utilize the identical ReactJS hook across multiple components

I've created a hook that pulls data from an API and stores the result in my component's state using setAllCommunitiesFromSponsor. Now I want to use this same hook in another component. Instead of copying and pasting, what is the best way to imp ...

Using createStackNavigator along with createBottomTabNavigator in React Navigation version 5

I have recently started working with react native and I am using the latest version of react-navigation (v.5) in my react-native application. However, I encountered errors when trying to use createStackNavigator and createBottomTabNavigator together within ...

Obtaining a complex object from a Checkbox set in AngularJS through the use of ngModel

Hey there! I've been searching on Stack Overflow regarding this topic, but I haven't found a solution that matches exactly what I need. If you want to take a look at the code, here is a JSFiddle link for reference: http://jsfiddle.net/gsLXf/1/ ...

Display <div> exclusively when in @media print mode or when the user presses Ctrl+P

Looking for a way to create an HTML division using the div element that is only visible when the print function is used (Ctrl+P) and not visible in the regular page view. Unfortunately, I attempted the following method without success. Any advice or solut ...

Creating Object of Objects in TypeScript: A Comprehensive Guide

Assuming I have a structure similar to this: interface Student { firstName: string; lastName: string; year: number; id: number; } If I intend to handle an array of these structures, I can simply specify the type as Student[]. Instead of utilizin ...

Ensure that the HTML input only accepts numbers and email addresses

Is there a way to restrict an HTML input field to only accept numbers and email IDs? <input id="input" type="text" /> ...

Ways to retrieve the identifier of an iframe

document.getElementById(Iframe_id).contentWindow.addEventListener("blur", blurtest, true); This line of code assigns the blur event to an iframe and it is functioning properly. However, when in function blurtest(e) { alert(e.target.id); } An alert ...