Невозможно получить доступ к состоянию внутри функции

Я использую React Native для своего приложения, и в какой-то момент я заметил, что мне приходится каждый раз вводить this.state.bar[this.state.foo][SOME_NUMBER] в своих компонентах.

Это отлично работает, но я хочу сделать свой код чище, вместо этого вызывая функцию. Итак, я построил это:

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

Однако, когда я запускаю это в клиенте Expo, я получаю следующую ошибку:

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

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

Вот мой весь код.

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>
        );
    }
}

Я попытался разместить функцию text() вне класса App, но получил ту же ошибку.

Когда я поместил его вне render() в App, я получил ошибку unexpected token.

Когда я определил this.state в constructor(props) и поместил text() в constructor, я получил ReferenceError: Can't find variable: text

использовать функцию-массив

Thomas 19.10.2018 16:42

@ Томас, я думаю, вы имели в виду arrow-function?

Sergio Moura 19.10.2018 16:44
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
13
2
27 601
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Здесь есть несколько проблем. Во-первых, вам нужно привязать функцию text к классу в конструкторе. Вам также необходимо переместить функцию text из метода рендеринга и добавить ее как метод класса (без function перед именем функции):

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>
    );
  }
}

Выдает Can't Find variable: text

Mrigank Pawagi 19.10.2018 16:44

@MrigankPawagi, используя ответ Чейза, вам необходимо использовать this.text внутри функции render, поскольку функция недоступна как ключевое слово внутри функции render. Вы можете в верхней части функции рендеринга выполнить const text = this.text и с этого момента использовать его без this.

Sergio Moura 19.10.2018 16:46
Ответ принят как подходящий

Ваша проблема ограничена.

this, к которому вы пытаетесь получить доступ внутри функции txt(), указывает на свой собственный this, а не на внешний компонент this.

Есть несколько способов исправить это. вот несколько:

Используйте стрелочные функции

Вы можете преобразовать txt в стрелочную функцию, чтобы использовать внешний this:

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

Вы можете привязать функцию к использованию внешнего this

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


    const txt = _txt.bind(this);

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

Вы можете создать дополнительную переменную, указывающую на внешний this.

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

Другие подходы

  • Вы можете переместить функцию txt за пределы функции рендеринга и привязать ее к компоненту this.
  • Вы можете использовать стрелочную функцию внутри блока класса компонента, который будет выглядеть так, как будто вы связали его с this компонента.
  • Вы можете передать состояние в качестве параметра функции

... и я уверен, что есть несколько других способов исправить это поведение. Вам просто нужно знать, когда вы используете компонент this или какой-нибудь другой this.

Большое спасибо! Работал как шарм! Я использовал 2-й подход, добавил const text = _text.bind(this) и работает! В принципе, я знал, что мне нужно использовать bind(), но не мог понять, где и как!

Mrigank Pawagi 19.10.2018 16:47

«Проблема» с привязкой таким образом (или даже с созданием функций внутри функции рендеринга в этом отношении) заключается в том, что вы создаете новый элемент функции каждый раз при рендеринге вашего компонента. Это одна из причин, по которой НЕ стоит создавать функции внутри функции рендеринга для очень больших компонентов.

Sergio Moura 19.10.2018 16:49

Я понимаю вашу точку зрения - к счастью, моя функция небольшая! Спасибо!

Mrigank Pawagi 20.10.2018 15:08

Другие вопросы по теме