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?

1

3 Answers 3

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)

Sign up to request clarification or add additional context in comments.

Comments

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.

3 Comments

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)
I've changed the response variable to an array and now there's no error but nothing's being displayed
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.
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>
        );
    }
}

4 Comments

thanks for the help but I was getting an error in the browser saying map was not a function
Sorry, response was initialized as a string. Edited answer. The error was at this line, right? {this.state.response.map(item => (<p>{item.name}</p>))}
I think so yeh, I've changed my JSON file to an array format as suggested above and have changed my response variable to an empty list
If your JSON is an array now, you can skip the Object.keys().... bit in your componentDidMount method

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.