0

I'm very new to React. I've set up a Nodejs back end which reads a JSON file in the following format:

{
    "cert1" : {
        "name" : "www.google.com",
        "state" : "valid",
        "days" : "482"
    },
    "cert2" : {
        "name" : "www.facebook.com",
        "state" : "valid",
        "days" : "182"
    },
    .
    .
    .
}

I want to display this data in a table and first need to put it into an array. I've managed to display www.google.com using the following code.

class App extends Component {
  state = {
    name  : '',
    state : '',
    days  : '',
    response : ''
  };


  componentDidMount() {
    this.callApi()
      .then(res => {
        this.setState({ 
          response: res.cert1.name
        })
      })
      .catch(err => console.log(err));
  }


  callApi = async () => {
    const response = await fetch('/list-certs');
    const body = await response.json();

    if (response.status !== 200) throw Error(body.message);

    return body;
  };

  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          {this.state.response}
        </p>
      </div>
    );
  }
}

How do I map over the whole JSON file and populate some arrays with all the entries? Right now I'm calling res.cert1.name but each cert entry in the JSON file has a different name (cert1, cert2, cert3 etc.) so how do I convert res.cert1.name into a generic call for any cert entry in the JSON file?

tnoel999888
  • 584
  • 3
  • 12
  • 29
  • possible duplicate https://stackoverflow.com/questions/38742334/what-is-right-way-to-do-api-call-in-react-js – HADI Apr 09 '18 at 09:04

3 Answers3

1

Ideally you'd want your JSON to be an array, rather than an object of objects:

[
    {
        "name" : "www.google.com",
        "state" : "valid",
        "days" : "482"
    }, {
        "name" : "www.facebook.com",
        "state" : "valid",
        "days" : "182"
    }
]

Then on the frontend you can grab each cert's name with res.map(x => x.name)

UncleDave
  • 6,872
  • 1
  • 26
  • 44
0

You can use Object.keys and Array.map to build an array out of your JSON object and map over that to render your elements.

Sample:

class App extends Component {
    state = {
        name  : '',
        state : '',
        days  : '',
        response : []
    };


    componentDidMount() {
        this.callApi()
            .then(res => {
                this.setState({
                    response: Object.keys(res).map(key=>({...res[key], id:key}))
                })
            })
            .catch(err => console.log(err));
    }


    callApi = async () => {
        const response = await fetch('/list-certs');
        const body = await response.json();

        if (response.status !== 200) throw Error(body.message);

        return body;
    };

    render() {
        return (
            <div className="App">
                <div className="App-header">
                    <img src={logo} className="App-logo" alt="logo" />
                    <h2>Welcome to React</h2>
                </div>
                <p className="App-intro">
                    {this.state.response.map(item => (<p>{item.name}</p>))}
                </p>
            </div>
        );
    }
}
Chirag Ravindra
  • 4,760
  • 1
  • 24
  • 35
0

Ideally you want the json results to be an array.

on retrieval from the api you can set the state with the results.

it depends what your api looks like, however if you return your json object with an array of items in it and store it in the state....

componentDidMount() {
    this.callApi()
      .then(res => {
        this.setState({ 
          results: res.body
        })
      })
      .catch(err => console.log(err));
  }

You can then do a map function in your render.

render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Welcome to React</h2>
        </div>
        <p className="App-intro">
          { this.state.results.map((row) => {
               return <p>{row.name}</p>
          }) }
        </p>
      </div>
    );
  }

Hope this helps.

Daryl
  • 195
  • 5
  • thanks for the help, but I'm getting at error in the browser saying: App.js:44 Uncaught TypeError: this.state.response.map is not a function at App.render (App.js:44) at ReactCompositeComponent.js:793 at measureLifeCyclePerf (ReactCompositeComponent.js:74) – tnoel999888 Apr 09 '18 at 09:24
  • I've changed the response variable to an array and now there's no error but nothing's being displayed – tnoel999888 Apr 09 '18 at 09:52
  • Hi @tnoel999888 it could be because the state results is not an array to begin with... in set state use this.setState({results:[]}); Also ensure the response from the server is coming back as an array not an object. – Daryl May 22 '18 at 11:54