2

i created an state in constructor, and setState in componentDidmount, when i try to render that state object to screen, it is throwing error, server im using is node API, and every other things are working fine. help me to solve this issue

app.js (react)

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';

class App extends Component {
  constructor(props) {
    super(props);
    this.State = {
      messages:[]
    }
  }
  componentDidMount() {
    axios.get('/patient/billing_get')
      .then((result) => {
        const messages = result.data
        console.log(messages);
        this.setState({
          messages: [...messages]
        })
      })
  }

  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
          <div>{this.State}</div>
         </p>
     </div>
    );
  }
}

export default App;

route function which im calling from node API:

function billing_get(req,res) {
    res.send("get method working")
}

Note : i have created this project by modifying create-react-app, and i have added proxy under react package.json to establish connection between node API and react

complete error message:

Objects are not valid as a React child (found: object with keys {messages}). If you meant to render a collection of children, use an array instead.
    in div (at App.js:42)
    in p (at App.js:40)
    in div (at App.js:35)
    in App (at index.js:7)
./src/index.js
src/index.js:7

   4 | import App from './App';
   5 | import registerServiceWorker from './registerServiceWorker';
   6 | 
>  7 | ReactDOM.render(<App />, document.getElementById('root'));
   8 | registerServiceWorker();
   9 | 
  10 | 

This screen is visible only in development. It will not appear if the app crashes in production.
Open your browser’s developer console to further inspect this error.
Pritish Vaidya
  • 21,561
  • 3
  • 58
  • 76
LogaKrishnan
  • 491
  • 1
  • 9
  • 24

3 Answers3

3

You cannot render the state object (note: lowercase, not State!), the following will never work:

<div>{this.state}</div>

Instead, pull off properties like the following:

class Example extends React.Component {
  constructor () {
    super()
    this.state = {
      messages: ['hi', 'bye']
    }
  }
  
  render () {
    // pull off messages array from state, then map over it to get each message
    const { messages } = this.state 
    return (
      <div>
        {messages.map(message => (
          <div>{message}</div>
        ))}
      </div>
    )
  }
}

ReactDOM.render(
 <Example />, 
 document.getElementById('root')
)
<div id='root'></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
vapurrmaid
  • 2,287
  • 2
  • 14
  • 30
2

At first rename this.State to this.state, state definition should be lowercase.

In app component you render object in <div /> jsx elemnt, it is incorrect. Try to map your messages and return separate element for each entity:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';

class App extends Component {
  constructor(props) {
    super(props);
    this.State = {
      messages:[]
    }
  }
  componentDidMount() {
    axios.get('/patient/billing_get')
      .then((result) => {
        const messages = result.data
        console.log(messages);
        this.setState({
          messages: [...messages]
        })
      })
  }

  render() {
   const { messages }  = this.state;
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <p className="App-intro">
          To get started, edit <code>src/App.js</code> and save to reload.
          <div>
           {messages.map(item => <span key={messages.indexOf(item)}>{item}</span>)}
          </div>
         </p>
     </div>
    );
  }
}

export default App;

Edit validate html

render() {
   const { messages }  = this.state;
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h1 className="App-title">Welcome to React</h1>
        </header>
        <div className="App-intro">
          <p>To get started, edit <code>src/App.js</code> and save to reload.</p>
          <div>
           {messages.map(item => <span key={messages.indexOf(item)}>{item}</span>)}
          </div>
         </div>
     </div>
    );
  }
Artem Mirchenko
  • 2,140
  • 1
  • 9
  • 21
  • thanks for the reply, still getting this error when using your code, Warning: validateDOMNesting(...):
    cannot appear as a descendant of

    . in div (at App.js:34) in p (at App.js:32) in div (at App.js:27) in App (at index.js:7)

    – LogaKrishnan Apr 17 '18 at 12:43
  • 1
    This error occurs because html nesting invalid. I edit my answer to make it valid in your render method. – Artem Mirchenko Apr 17 '18 at 12:51
1

Afternoon m8,

Change State to state and then in your render function change <div>{this.State}</div> to <div>{this.state.messages}</div> or change to the following to have more control on how to render each message.

 <div>
  {
      this.state.messages.map((message) => {
           return (<div>{message}</div>);
      })
  }
 </div>

Also you need to change how you're updating the state in the axios callback, change this

axios.get('/patient/billing_get')
  .then((result) => {
    const messages = result.data
    console.log(messages);
    this.setState({
      messages: [...messages]
    })
})

To this

axios.get('/patient/billing_get')
  .then((result) => {
    // Because you're just returning a string and not an array..
    const message = result.data
    this.setState({
      messages: [...this.state.messages, messages]
    })
})
TheNickyYo
  • 2,389
  • 5
  • 20
  • 28
  • thanks for the reply, still getting this error when using your code, Warning: validateDOMNesting(...):
    cannot appear as a descendant of

    . in div (at App.js:34) in p (at App.js:32) in div (at App.js:27) in App (at index.js:7)

    – LogaKrishnan Apr 17 '18 at 12:49
  • 1
    @FunWorld updated my answer to fix it for you. also, change your div tags on line 32 to a span tag.. looks like you've got linting. – TheNickyYo Apr 17 '18 at 12:58
  • Thank you so much for the reply :) – LogaKrishnan Apr 17 '18 at 14:09