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

Exploring the TypeScript compiler API to read and make updates to objects is an interesting

I'm delving into the world of the typescript compiler API and it seems like there's something I am overlooking. I am trying to find a way to update a specific object in a .ts file using the compiler API. Current file - some-constant.ts export co ...

Preventing page refresh when typing in a form input: Tips and tricks

I'm currently puzzled by a small issue. In my web application, I have a chat box that consists of an input[type='text'] field and a button. My goal is to send the message to the server and clear the input field whenever the user clicks the b ...

What is the best way to save the output of an asynchronous function into a class attribute?

Currently, I am attempting to retrieve HTML content from a webpage by utilizing a class equipped with a single asynchronous method. This process involves Typescript 3.4.3 and request-promise 4.2.4. import * as rp from 'request-promise'; class H ...

A beginner's guide to crafting a knex query with MySQL language

Within MySQL Workbench, I currently have the following code: USE my_db; SELECT transactions.created_at, price FROM transactions JOIN transactions_items ON transactions.id = transactions_items.transaction_id JOIN store_items ...

NextJS: Issue: Accessing a client module from a server component is not allowed. The imported name must be passed through instead

My current NextJS setup is structured as shown below: app/page.js 'use client'; import React from 'react'; export default function Home() { return (<div>Testing</div>); } app/layout.js export const metadata = { title ...

Using jQuery to create a draggable element with a visual indicator that represents a link between two items

Utilizing the "parenting" tool in Adobe AfterEffects allows you to connect layers together. Simply click and hold the icon, then drag it to its destination. A line is drawn from the parent layer to your cursor as a visual guide. I have mastered draggable/ ...

How to achieve the wrapping functionality in ReactJS that is similar to

Is there a ReactJS equivalent to jQuery's wrap method? I want to wrap menuContents with the following element: <ul className="nav nav-pills nav-stacked"></ul> The contents of menuContents are generated like this: let menuContents = thi ...

Utilizing Sequelize validation through condition objects

const db = require("../models"); const Meet = db.meet; checkDuplicateTime = (req, res, next) => { Meet.findAll({ where: { tanggal: req.body.date, waktu: req.body.time } }).then(time => { ...

Clear the modal form in Codeigniter and AJAX upon closing the edit modal

Having an issue with my modal form - when I open the edit modal, the data is fetched and that part works well. However, when I close the modal and try to add a new user, the data is automatically fetched again. Why is this happening? Shouldn't the for ...

Loading content dynamically into a div from an external or internal source can greatly enhance user experience on a website. By

As I work on my website, I am incorporating a div structure as shown below: <div class="container"> <div class="one-third column"> <a id="tab1" href="inc/tab1.html"><h2>tab1</h2></a> </div> & ...

Having trouble deploying a Heroku app using Hyper? Here's a step-by-step guide to

After running the following commands: https://i.stack.imgur.com/WZN35.png I encountered the following errors: error: src refspec main does not match any error: failed to push some refs to 'https://git.heroku.com/young-brook-98064.git' Can anyon ...

What is the proper way to incorporate a ref within a class component?

I am encountering an issue with my class component. I'm wondering if there is a comparable feature to useRef() in class components? Despite several attempts at researching, I have yet to find a solution. ...

Can you explain the execution process of this Http.post method and provide details about the code path it follows

As I delve into the world of web development, one aspect that has me stumped is the functionality of the Http.post section within a project I stumbled upon on GitHub. Specifically, this pertains to an ExpressJS with Typescript repository I came across. So, ...

Issue when attempting to update user profile picture using Mongoose schema and Cloudinary

updateProfile: async function(req, res) { try { const update = req.body; const id = req.params.id; if (!req.files || Object.keys(req.files).length === 0) { return res.status(400).send('No files were uploaded.&a ...

Elusive Essence: Mysterious Origins of the

Beginner in the world of Ionic and Angular. I am attempting to create a test app and incorporating the factory function. I obtained the design from Ionic Creator and now trying to add my code to it. Here is my controller file. angular.module('app.c ...

The Google map is failing to load on the webpage

My id="ieatmaps" is set up to call the googlemaps.js, but for some reason, it's not displaying correctly. I must be missing something. function initMap() { var map = new google.maps.Map(document.getElementById('ieatmaps'), { c ...

More efficient methods for handling dates in JavaScript

I need help with a form that requires the user to input both a start date and an end date. I then need to calculate the status of these dates for display on the UI: If the dates are in the past, the status should be "DONE" If the dates are in the future, ...

Guide to resolving a blank webpage issue post running 'npm run build'

I am currently in the process of working on a project that involves Vue and Firebase. Unfortunately, I have encountered an issue where my development server is no longer rendering new routes from my Vue router after building and deploying to production. F ...

Utilizing Cookies within an HTML Page

My current code is functioning perfectly, accurately calculating the yearly income based on the input "textmoney." I have a link to a more advanced calculator for a precise prediction. My goal is to find a way for the website to retain the data input from ...

SPFx WebPart - Tabbed Interface

I am new to developing SPFX WebParts and currently working on creating a Tab WebPart. The HTML appears to be rendering correctly, but I'm facing issues with the Javascript functionality not firing as expected. Any assistance or guidance on how to prop ...