Soy muy nuevo en React y, aunque hice algunos progresos con los que estoy contento, me encontré con un obstáculo con el que estoy atrapado y he estado durante más de un día.

Estoy creando una pequeña aplicación que usa React en la interfaz y un servidor .NET Core API para proporcionar los datos.

Hasta ahora, el siguiente código funciona:

import React, { Component } from 'react';

export class LGSRValidation extends Component {
  displayName = LGSRValidation.name

  constructor(props) {
    super(props);
    this.state = { lgsr: [], loading: true };

    fetch('api/FormValidation/LGSR')
      .then(response => response.json())
      .then(data => {
        this.setState({
          lgsr: data,
          loading: false
        });
      });
  }

  static renderLGSRTable(lgsr) {
    return (
      <table className='table'>
        <thead>
          <tr>
            <th>Job Number</th>
            <th>Job Type</th>
            <th>UPRN</th>
            <th>Gas Register Number</th>
            <th>Service Date</th>
          </tr>
        </thead>
        <tbody>
          <tr key={lgsr.jobnumber}>
            <td>{lgsr.jobNumber}</td>
            <td>{lgsr.jobType}</td>
            <td>{lgsr.uprn}</td>
            <td>{lgsr.gasRegisterNumber}</td>
            <td>{lgsr.serviceDate}</td>
          </tr>
        </tbody>
      </table>
    );
  }

  render() {
    let contents = this.state.loading
      ? <p><em>Loading...</em></p>
      : LGSRValidation.renderLGSRTable(this.state.lgsr);

    return (
      <div>
        <div>
          <h1>{this.displayName}</h1>
          <p>This component demonstrates fetching data from the server.</p>
          {contents}
        </div>
      </div>
    );
  }
}

Lo que simplemente hace es llamar a mi API para devolver un solo objeto al código del lado del cliente y representar cada propiedad dentro del objeto en una columna de tabla separada.

Lo que intento hacer es introducir un botón que onClick volverá a llamar a la API, extraer un nuevo objeto y cambiar los valores en la tabla para los nuevos valores de propiedad. Estoy contento con mi código del lado del servidor y la creación de los objetos aleatorios, pero mi código del lado del cliente simplemente no funciona.

Estoy introduciendo el botón dentro de las etiquetas principales del componente de esta manera:

render() {
  let contents = this.state.loading
    ? <p><em>Loading...</em></p>
    : LGSRValidation.renderLGSRTable(this.state.lgsr);

  return (
    <div>
      <div>
        <h1>{this.displayName}</h1>
        <p>This component demonstrates fetching data from the server.</p>
        {contents}
      </div>


      <button onClick={this.getData}>
        Next
      </button>
    </div>
  );
}

Lo que parece rendir bien. También estoy presentando una función getData como esta más arriba:

getData() {
    fetch('api/FormValidation/LGSR')
        .then(response => response.json())
        .then(data => {
            this.setState({
                lgsr: data,
                loading: false
            });
        });

    this.setState({
       contents : this.state.lgsr
    });
}

Sospecho que es en esta parte donde me estoy equivocando.

¿Puede aconsejarme cómo puedo hacer clic en mi nuevo botón para llamar a la API, devolver algunos datos y pasar las propiedades del objeto lgsr a las columnas de la tabla correspondiente; reemplazando los datos anteriores con los nuevos datos.

3
Stu1986C 15 sep. 2018 a las 00:23

3 respuestas

La mejor respuesta

Debe vincular su getData() a su constructor para poder usar this para su componente en lugar de la función actual.

this.getData = this.getData.bind(this);

Una forma más rápida es usar la función de flecha como la siguiente ...

getData = () => {....}

Con suerte, esto debería solucionar su problema y permitirle usar this.state

1
SGhaleb 15 sep. 2018 a las 06:14

¿Qué estás tratando de lograr aquí? ¿Puedes pegar tu código final?

Veo algo terrible aquí. Su 'carga' ya está declarada en el estado de su componente y está actualizando el estado de 'contenido' con los datos lgsr. Y en su render, ha declarado contenidos como this.state.loading

 constructor(props) {
    super(props);
    this.state = { lgsr: [], loading: true };

     /*some code here*/

    getData () {
        fetch('api/FormValidation/LGSR')
            .then(response => response.json())
            .then(data => {
                this.setState({
                    lgsr: data,
                    loading: false 
               });
            });

        this.setState({
           contents : this.state.lgsr
        });
    }

      render() {
        let contents = this.state.loading
0
Jaz 15 sep. 2018 a las 07:36

Veo 4 formas de mejorar tu código:

  1. Cargue datos en el método de ciclo de vida componentDidMount en lugar del constructor del componente ( más información ). Esto no debería estar relacionado con su problema, pero es más seguro asegurarse de que el componente se haya montado antes de que posiblemente configure el estado.

  2. Como SGhaleb mencionó, asegúrese de que su función getData esté enlazada, ya sea usando una función de flecha o la alternativa de enlace, de lo contrario, this.getData no está definido y el botón onClick no debería funcionar. Puede usar getData para su solicitud inicial de no tener código duplicado en su clase.

  3. En getData establece la propiedad content del estado, pero lo hace fuera de la devolución de llamada de la solicitud. Su valor puede ser el objeto lgsr nuevo o el antiguo de la nueva solicitud. Compruebe que desea esto o muévalo a la devolución de llamada de recuperación.

  4. Use un componente dedicado para renderizar la tabla LGSR en lugar de usar un método de renderizado estático y pasarle los datos requeridos a través de accesorios. De nuevo, nada que ver con tu pregunta.

2
sn42 15 sep. 2018 a las 07:13