Source:  Twitter logo

I am using React Native for my application, and at one point, I noticed that I have to type this.state.bar[this.state.foo][SOME_NUMBER] every time, within my components.

This works perfectly fine, but I want to make my code cleaner by calling a function instead. So, I constructed this:

function txt(n){
    return this.state.bar[this.state.foo][n];
}

However, when I run this in the Expo client, I get the following error:

TypeError: undefined is not an object (evaluating 'this.state.bar')

This error is located at:
    in App...
    ....

Here is my entire code.

import React, 
    { Component } 
from 'react';
import { 
     ... 
} from 'react-native';

export default class App extends React.Component {
    state = {
        foo: 'ABC',
        bar: {
            'ABC': [
                '...',
                '...',
                '...'
            ]
        }
    };
    render() {
        function txt(n){
            return this.state.bar[this.state.foo][n];
        }
        return (
            <View>
                ...  
            </View>
        );
    }
}

I tried placing the text() function outside the App class, but got the same error.

When I placed it outside render() in App, I got an unexpected token error.

When I defined this.state within a constructor(props) and placed text() within the constructor, I got ReferenceError: Can't find variable: text

Your problem is scoping.

The this that you're trying to access inside the txt() function is pointing to its own this, and not the outer component this.

There are several ways to fix this. here's a few:

Use arrow functions

You can transform txt into an arrow function to use the outer this:

render() {
    const txt = (n) => {
        return this.state.bar[this.state.foo][n];
    }
    return (
        <View>
            ...  
        </View>
    );
}

You can bind the function to use the outer this

render() {
    function _txt(n){
        return this.state.bar[this.state.foo][n];
    }


    const txt = _txt.bind(this);

    return (
        <View>
            ...  
        </View>
    );
}

You can create an additional variable that points to the outer this

render() {
    const self = this;
    function txt(n){
        return self.state.bar[self.state.foo][n];
    }
    return (
        <View>
            ...  
        </View>
    );
}

Other approaches

  • You can move the txt function to outside of the render function and bind it to the component this.
  • You can use an arrow function inside the component class block, which will seem like you've bound it to the component's this.
  • You can pass the state as a parameter to the function

...and I'm sure that there are several other ways to fix this behaviour. You just need to know when you're using the component's this or some other this.

27 users liked answer #0dislike answer #027
Sergio Moura profile pic
Sergio Moura

A few issues here. First, you need to bind the text function to the class in the constructor. You also need to move the text function out of the render method and add it as a class method (no function in front of function name):

import React,
{ Component }
  from 'react';
import {
...
} from 'react-native';

export default class App extends React.Component {

  constructor () {
    super();
    this.state = {
      foo: 'ABC',
      bar: {
        'ABC': [
          '...',
          '...',
          '...'
        ]
      }
    };
    this.text = this.text.bind(this);
  }

  text (n) {
    return this.state.bar[this.state.foo][n];
  }

  render() {
    return (
      <View>
        ...
      </View>
    );
  }
}
1 users liked answer #1dislike answer #11
Chase DeAnda profile pic
Chase DeAnda

Copyright © 2022 QueryThreads

All content on Query Threads is licensed under the Creative Commons Attribution-ShareAlike 3.0 license (CC BY-SA 3.0).