0

I'm receiving through props some data:

this.props.data = [
         {"game_id":4,"city":"Pyeongchang","year":2018},
         {"game_id":2,"city":"Rio de Janeiro","year":2016}
];

this is what is received and it can be sent to render and show it on the screen.

The problem is when I want to access inside of this array.

For example:

const firstObj = this.props.data[0];
console.log('firstObj: ', firstObj); // prints [

I was expecting to the the first object ({"game_id":4,"city":"Pyeongchang","year":2018}) but it took the first char from this.props.data.

So I was thinking that the data is not well formatted.

console.log(typeof this.props.data); // -> string - it returns string which is weird

So I tried to convert it with JSON.parse:

const convertedData = JSON.parse(this.props.data); -> but this throws an error:

Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development.

Why is this happening and how can it be solved?

UPDATE

Data is coming from Node.js:

var express = require('express');
var router = express.Router();
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('./db/ocs_athletes.db');

router.get('/', function (req, res, next) {
  db.serialize(function () {
    db.all(
      'SELECT g.game_id, g.city, g.year, ar.athlete_id, ar.gold, ar.silver, ar.bronze FROM(Game g join AthleteResult ar on g.game_id = ar.game_id) order by g.year desc',
      function (err, rows) {
        return res.send(rows);
      }
    );
  });
});

module.exports = router;

and in React app it is received in App.js:

import React from 'react';
import './App.css';
import Table from './components/Table';

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = { apiResponse: [] };
  }

  callAPI() {
    fetch('http://localhost:9000/testAPI')
      .then((res) => res.text())
      .then((res) => this.setState({ apiResponse: res }));
  }

  componentDidMount() {
    this.callAPI();
  }

  render() {
    return (
      <div className='App'>
        <header className='App-header'>
          <Table data={this.state.apiResponse} />
        </header>
      </div>
    );
  }
}
export default App;

From here it is send through props to Table component:

class Table extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const { data } = this.props;
    console.log('data: ', data); // prints the whole data

    console.log(typeof data); // prints string

    const convertData = JSON.parse(this.props.data); // throws the error I talked about


    return (
      <div>
        <table>
          <thead>
            <tr>{data}</tr>
          </thead>
        </table>
      </div>
    );
  }
}

export default Table;
Leo Messi
  • 5,157
  • 14
  • 63
  • 125
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/218008/discussion-on-question-by-leo-messi-convert-string-to-object-in-javascript). – Samuel Liew Jul 17 '20 at 06:33

2 Answers2

1

have you tried to convert your data to JSON when first receiving the response from the API? maybe you can try this

fetch(reqUrl, request)
    .then((response) => response.json())
    .then((responseJson) => {
        // your json result is here
    })
    .catch((error) => {

    })
  • This is right, OP is using `resp.text()` which returns the body as a string instead of the JSON. Also, OP should [check if the response is valid before parsing it](https://stackoverflow.com/q/51811598/1218980). – Emile Bergeron Jul 16 '20 at 14:36
-1

you should invoke this.callAPI in componentDidMount, not componentWillMount. Also, it would probably be simpler to initialize this.state.apiResponse as an empty array rather than a string so you don't have to convert it to a string and then back to an object with JSON.parse

Ethan Lipkind
  • 1,136
  • 5
  • 7
  • 1
    yeah looks like the root of the problem was using `response.text` instead of `response.json`. Nonetheless, in a class component you should make api calls in `componentDidMount`, not `componentWillMount` :) – Ethan Lipkind Jul 16 '20 at 19:20