2

this is my first time coding in Javascript/React JS so I'm not sure what is wrong here. getLicensees() send a GET request it my API and returns all the licensees. This works so far, also the console logs are working and printing the correct value.

constructor(props) {
super(props);

this.state = {licensees: []};

let licenseeResponse = LicensingService.getLicensees()
  .then(licensees => {
    this.state.licensees = licensees;
    console.log("component", licensees);
    console.log(licensees[0].city);
  });
}

I'm trying to generate a table out of all the information’s inside my licensees object. But I can’t use this.state.licensees[0].city inside my render() method.

render() {
return (
  <main id="content">
    <div id="head">
      <h4 className="headline">
        Liste aller Lizenznehmer
      </h4>

      <div className="licenseeTable">
        <table>
          <tr>
            <th>Lizenz nehmer</th>
            <th>Aktuelles Zertifikat</th>
            <th>Details</th>
          </tr>
          <tr>
            <td>{this.state.licensees[0].city}</td>
            <td>test2</td>
            <td>test3</td>
          </tr>
        </table>
      </div>
    </div>
  </main>
);
}

how can I do this properly?

--My solution:

componentDidMount() {
console.log('component did mount..', this);
LicensingService.getLicensees()
  .then(licensees => {
    this.setState({licensees});
    console.log(licensees);
  });
}

...

{
            this.state.licensees.map(license => {
              return <tr>
                <td>{license.company}</td>
                <td>{license.testCertificate.toString()}</td>
                <td>{license.city}</td>
              </tr>
            })
          }

this.setState({licensees}) is the correct way to assign value to the state object.

3
  • 1
    *Offtopic : You might want to look at the official docs, I think there is a minor issue in your set state logic, reactjs.org/docs/state-and-lifecycle.html, although the state in React is an object and it's ok to set it directly in the constructor, it's more appropriate to use the setState method outside the constructor (for exmaple in the componentDidMount hook) when fetching some data (i assume getLicensees is some async code) Commented Jun 4, 2018 at 10:34
  • Have you changed your setState to this this.setState({licensees}); ?? Commented Jun 4, 2018 at 12:55
  • yes I have :--) Commented Jun 4, 2018 at 13:29

2 Answers 2

4

The problem is that although you have your API request in constructor, it will return a response only after the render cycle and since you are directly mutating state in the resolved promise, a re-render is not called.

What you need to do is to have the API call in componentDidMount lifecycle method and update your state using setState

constructor(props) {
   super(props);

   this.state = {licensees: []};

}

componentDidMount() {
    LicensingService.getLicensees()
      .then(licensees => {
        this.setState({licensees});
        console.log("component", licensees);
        console.log(licensees[0].city);
    });
}
Sign up to request clarification or add additional context in comments.

7 Comments

Thank you! This helps me :)
Glad to have helped :-)
but there is another problem, he’s saying that: Objects are not valid as a React child (found: object with keys {city, ...} . If you meant to render a collection of children, use an array instead. I tried to form it into an array but it’s says it can’t do it because its undefined I tried to form it into an array but its says it cant do it becouse its undefined
can you add your licences array in the question
Edit the wrong post facepalm, see it now on my original question :)
|
1

First you want to move the api call to componentDidMount instead of doing it in a constructor, doing so wont work as your component would already have rendered before you get the data.

Then you need to use setState to cause your render function to be called so that the updated value is displayed. like this :

this.setState({licensees}); instead of mutating the state directly like

this.state.licensees = licensees;

read more here Using State Correctly

You would also want to wait for the value untilll you try to access it so you will have to make this change in your render as well Instead of this :

<td>{this.state.licensees[0].city}</td>

do this

{this.state.licensees && <td>{this.state.licensees[0].city}</td>} //only render when you have the value in the state.

Comments

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.