Estoy tratando de entender algunos conceptos en reactjs, pero no puedo entender el anidamiento de funciones. Creé el siguiente ejemplo para investigar mi preocupación.

En el ejemplo a continuación, renderizo parte del contenido cuyo valor proviene de una serie de funciones anidadas. Sin embargo, aparece el error "Error de tipo no capturado: no se puede leer la propiedad 'renderInnerContent' de undefined". ¿Pueden ayudarme a comprender qué está sucediendo y cómo resolver este problema? Mi motivo principal es comprender cómo abstraer las cosas en diferentes funciones.

import React, { Component } from 'react';

export default class MyComponent extends Component {
  renderInnerContent() {
    return (
      <div>Innercontent</div>
    )
  }

  renderContent() {
    let data = ["a","b","c"];
    const displaydata = data.map(function(point){
      return (
        <div key={point}>{this.renderInnerContent()}</div>
      )
    });
    return (
      <div>{displaydata}</div>
    )
  }

  render() {
    return (
      <div>{this.renderContent()}</div>
    )
  }
}
1
asanas 8 may. 2016 a las 11:03

4 respuestas

La mejor respuesta

this no está definido en el contexto de esa función:

function(point){
  return (
    <div key={point}>{this.renderInnerContent()}</div>
  )
}

Porque es una nueva función. Tiene diferentes opciones para pasar this a esa función:

1- Función de flecha gorda:

renderContent() {
   let data = ["a","b","c"];
   const displaydata = data.map((point) => {
      return (
        <div key={point}>{this.renderInnerContent()}</div>
       )
   });
   return (
      <div>{displaydata}</div>
   )
}

2- Definir una variable:

renderContent() {
   let data = ["a","b","c"];
   let _this = this;
   const displaydata = data.map(function(point){
      return (
        <div key={point}>{_this.renderInnerContent()}</div>
       )
   });
   return (
      <div>{displaydata}</div>
   )
}

3- Use bind:

renderContent() {
   let data = ["a","b","c"];
   const displaydata = data.map(function(point){
      return (
        <div key={point}>{this.renderInnerContent()}</div>
       )
   }.bind(this));
   return (
      <div>{displaydata}</div>
   )
}

PD: No estoy seguro de que ninguno de estos no funcione en React.

6
ykaragol 8 may. 2016 a las 08:26

El más corto que uso es este:
<div>{this.renderContent.bind(this).call()}</div>.

A veces se ponen un poco feos desde mi punto de vista, pero es el más corto.

1
Kairxa 8 may. 2016 a las 10:16

El problema principal aquí es que está pasando una función a data.map y en ese ámbito 'esto' no es su ámbito externo (ChartsArea) pero se refiere por defecto al objeto global (ventana) porque es una función anónima.

Entonces, para que funcione, puede hacer esto:

var that = this; 

const displaydata = data.map(function(point){
      return (
        <div key={point}>{that.renderInnerContent()}</div>
      )
    });

O pase su contexto en el segundo argumento de .map:

const displaydata = data.map(function(point){
      return (
        <div key={point}>{that.renderInnerContent()}</div>
      )
    }, this);

O use bind:

const displaydata = data.map(function(point){
      return (
        <div key={point}>{that.renderInnerContent()}</div>
      )
    }.bind(this));

O use las funciones de flecha como alguien más señaló.

2
JohnIdol 8 may. 2016 a las 08:28