Retrieve the value of a variable to access an object property dynamically in React Native using TypeScript

As I attempted to create dynamic styles for this component, my goal was to determine the styles based on a string passed in as a property. Here is the code snippet:

export type MyComponentProps = {
  styleName: string;
}

const MyComponent = (props: MyComponentProps) => {
  const { styleName } = props;
  
  return (
    <View
      style={[
        styles['container'],
        styles[`view${styleName}`],
      ]}>
      <Text
        style={[
          styles['text'],
          styles[`text${styleName}`],
        ]}>
        Hello World
      </Text>
    </View>
  );
}


const styles = StyleSheet.create({
  container: {
    width: '100%',
    alignItems: 'center',
  },

  viewDark: {
    backgroundColor: 'black',
  },

  viewLight: {
    backgroundColor: 'white',
  },

  text: {
    fontWeight: 'bold',
  },

  textDark: {
    color: 'white',
  },

  textLight: {
    color: 'black',
  },
}

However, I encountered an error stating:

'Element implicitly has an 'any' type because expression of type '`view${any}`' can't be used to index type '{ container: { width: string; alignItems: "center"; }; viewDark: { backgroundColor: string; }; viewLight: { backgroundColor: string; }; text: { ...; }; textDark: { ...; }; textLight: { ...; }; }'.

I wanted to avoid passing any styles directly through the props, as it's not commonly recommended.

Although unconventional, I intentionally used styles['container'] instead of styles.container, to highlight the distinction between the two cases with ${styleName} being the only variable factor.

Answer №1

Through our investigation, it has become evident that we can achieve this task by converting the dynamically generated string to a keyof the interface assigned to the styles variable. The following example demonstrates how:

export type MyComponentProps = {
  styleName: string;
}

const MyComponent = (props: MyComponentProps) => {
  const { styleName } = props;
  
  return (
    <View
      style={[
        styles['container'],
        styles[`view${styleName}` as keyof IStyles],
      ]}>
      <Text
        style={[
          styles['text'],
          styles[`text${styleName}` as keyof IStyles],
        ]}>
        Hello World
      </Text>
    </View>
  );
}

interface IStyles {
  container: object,
  viewDark: object,
  viewLight: object,
  text: object,
  textDark: object,
  textLight: object,
}

const styles: IStyles = StyleSheet.create({
  container: {
    width: '100%',
    alignItems: 'center',
  },

  viewDark: {
    backgroundColor: 'black',
  },

  viewLight: {
    borderColor: 'white',
  },

  text: {
    fontWeight: 'bold',
  },

  textDark: {
    color: 'white',
  },

  textLight: {
    color: 'black',
  },
}

Remember to define styles with the interface IStyles using const styles: IStyles = ...

Answer №2

There may be instances where the alternative solution doesn't seem to work, but I'll still include it for readers' reference. This method has proven to be reliable thus far without requiring the creation of an interface, which could be seen as a benefit.

export type MyComponentProps = {
  styleName: string;
}

const MyComponent = (props: MyComponentProps) => {
  const { styleName } = props;

  const viewStyle = `view${styleName}`; // Possibly easier to understand
  
  return (
    <View
      style={[
        styles['container'],
        `view${styleName}` == 'viewDark'
          ? styles['viewDark']
          : {},
        viewStyle == 'viewLight' // Using the more understandable option
          ? styles['viewLight']
          : {},
      ]}>
      <Text
        style={[
          styles['text'],
          `text${styleName}` == 'textDark'
          ? styles['textDark']
          : {},
          `text${styleName}` == 'textLight'
          ? styles['textLight']
          : {},
        ]}>
        Hello World
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    width: '100%',
    alignItems: 'center',
  },

  viewDark: {
    backgroundColor: 'black',
  },

  viewLight: {
    borderColor: 'white',
  },

  text: {
    fontWeight: 'bold',
  },

  textDark: {
    color: 'white',
  },

  textLight: {
    color: 'black',
  },
}

One drawback is that we need to manually write if statements to check each possible style individually, but the benefit is that it seems to be more dependable in practice.

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

Flexible type definition including omission and [key:string]: unknown

When I write code, I like to explain it afterwards: type ExampleType = { a: string; b: boolean; c: () => any; d?: boolean; e?: () => any; [inheritsProps: string]: unknown; // If this ^ line over is removed, TypeNoC would work as expecte ...

Navigating from a Card to a new View in Angular

I am currently developing a project using Angular (latest version). Within my application, I have the functionality to dynamically generate bootstrap cards from an Order Array and display them in my "Order-Item-Component through its respective template. ...

Unable to utilize MUI Dialog within a ReactDOMServer.renderToStaticMarkup() call

I recently started using the DIALOG component for the first time, expecting it to seamlessly integrate into my setup. However, much to my disappointment, it did not work as expected. After spending a considerable amount of time troubleshooting the issue, I ...

Troubleshooting compilation issues when using RxJS with TypeScript

Having trouble resolving tsc errors in the code snippet below. This code is using rxjs 5.0.3 with tsc 2.1.5 import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; import 'rxjs/Rx'; let subject ...

Angular Universal causing issues with updating the DOM component

@Component({ selector: 'mh-feature-popup', template: ` <div class="full"> <div> <div class="container-fluid" [@featurepop]="state"> <div class="row"> <div class="col-xs-12 col-md-4 col-md-offse ...

"Navigating through events with confidence: the power of event

Imagine I am developing an event manager for a chat application. Having had success with event maps in the past, I have decided to use them again. This is the structure of the event map: interface ChatEventMap { incomingMessage: string; newUser: { ...

"I am looking for a way to incorporate animation into my Angular application when the data changes. Specifically, I am interested in adding animation effects to

Whenever I click on the left or right button, the data should come with animation. However, it did not work for me. I tried adding some void animation in Angular and placed a trigger on my HTML element. The animation worked when the page was refreshed, bu ...

Removing a value from an array of objects in Angular 2

There is a single array that holds objects: one = [ {name: 'Name', key: '4868466'}, {name: 'Name', key: '4868466'}, {name: 'Name', key: '4868466'}, {name: 'Name', key: & ...

After upgrading Expo, the React Native Auth Session ceased to function

During my use of Expo SDK 48, my app successfully implemented Google and Facebook authentication with a web browser-based authentication method. Functional code: type AuthResponse = AuthSession.AuthSessionResult & { params: { access_token ...

Utilizing the useSearchParams() function to retrieve live data in Next.js

Is there anyone who has successfully migrated from the pages router to the app router in Next.js? I am facing an issue with dynamic data migration. In the pages router, dynamic data is retrieved on a page using useRouter().query, but in the app router, it ...

Ways to transfer JavaScript arguments to CSS style

Currently, I am developing a web service using Angular and Spring Boot. In this project, I have implemented cdkDrag functionality to allow users to place images in specific locations within the workspace. My goal is to maintain the placement of these image ...

There seems to be a problem with the [at-loader] node_modules@typesjasmine

My webpack build suddenly started failing with no package updates. I believe a minor version change is causing this issue, but I'm unsure how to resolve it. Can someone provide guidance on what steps to take? ERROR in [at-loader] node_modules\@t ...

Leverage the power of forkJoin in JavaScript by utilizing objects or sourcesObject

I'm currently facing an issue with my code snippet below: getInformations().subscribe( informations => { let subs = []; for (const information of informations) { subs.push(getOtherDetails(information.id)); } ...

The DataGrid is only displaying a single result instead of multiple results

I'm having difficulty displaying all the results in this MUI data table. Currently, it is only showing one result instead of all, and I can't figure out what I'm doing wrong. If you have any suggestions or best practices on how to properly ...

Issue: Incorrect hook usage. Hooks are designed to be used within the body of a function component. This error may occur due to one of the following reasons: 1

I've reviewed similar questions and attempted to apply the solutions provided, but it seems I'm missing something specific to my situation. My goal is to streamline my code by importing headers from a utils file and using them across different AP ...

Isolating a service from a component based on conditions in Angular 5

Within my root module, I have a service that is shared among all components. One of these components is named ComponentX module providers: [ BiesbroeckHttpService ], component constructor(private biesbroeckHttpService: BiesbroeckHttpService){} Som ...

My React JS page suddenly turned blank right after I implemented a setState() function within my functional component

I was working on my code and everything seemed fine until I tried to incorporate the setState function with setcategory and setvalue. However, after making this change, my react page suddenly went blank. Can anyone help me identify what went wrong and pr ...

When I receive a 404 response from the API, I aim to start my observable

How can I trigger my observable initialization when receiving a 404 response from the API? The code snippet below is not working as expected. const urlParams = { email: this.email }; this.voicesProfileObservable$ = this.service.request<any>( AVAI ...

Utilizing TypeScript's Exclude feature with a generic type

An update to dependencies in my TypeScript-based Nodejs project has led to compilation errors when working with a generic class that manages mongoose models. The root cause appears to be related to how TypeScript handles generic types. To illustrate the i ...

Creating a personalized event using typescript

I need help with properly defining the schema for an EventObject, specifically what should be included within the "extendedProps" key. Currently, my schema looks like this: interface ICustomExtendedProps { privateNote?: string; publicNote?: string; ...