简体   繁体   中英

Fetch data into React component and render it

Backend dev here trying to make a super scrappy app. Don't judge me. :P

Started from create-react-app. My App.js looks like this:

import React from 'react';
import ReactDOM from 'react-dom';
import './App.css';

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

    componentDidMount() {
        fetch('/api/requiredUsers')
            .then(response =>
                {
                    this.setState({foo: response.json()});
                    console.log(this.state.foo);
                }
            );
    }

    render() {
        return (
            <div>
                <table className="table">
                    <thead>
                    <tr>
                        <th scope="col">#</th>
                        <th scope="col">Name</th>
                        <th scope="col">Age</th>
                        <th scope="col">Number</th>
                    </tr>
                    </thead>
                    <tbody>
                    {this.state.foo.map(person => (
                        <tr key={person.id}>
                            <th scope="row">{person.id}</th>
                            <td>{person.name}</td>
                            <td>{person.age}</td>
                            <td>{person.number}</td>
                        </tr>
                    ))}
                    </tbody>
                </table>
            </div>
        )
    }
}

export default Table;

ReactDOM.render(<Table />, document.getElementById('root'));

The response I get from localhost:8080/api/requiredUsers (where I am running a springboot app):

[{"id":8,"name":"christoph","age":32,"number":"555-555-5555"},
{"id":9,"name":"debra","age":31,"number":"555-555-5555"},
{"id":10,"name":"eric","age":29,"number":"555-555-5555"},
{"id":19,"name":"richard","age":20,"number":"555-555-5555"},
{"id":14,"name":"santiago","age":25,"number":"(555)555-5555"}]

When I comment out , I get a console.log print of:

Promise {<pending>}
__proto__: Promise
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Array(5)
0: {id: 8, name: "christoph", age: 32, number: "555-555-5555"}
1: {id: 9, name: "debra", age: 31, number: "555-555-5555"}
2: {id: 10, name: "eric", age: 29, number: "555-555-5555"}
3: {id: 19, name: "richard", age: 20, number: "555-555-5555"}
4: {id: 14, name: "santiago", age: 25, number: "(555)555-5555"}
length: 5
__proto__: Array(0)

But when I don't comment it out, I get this error:

Uncaught TypeError: Cannot read property 'foo' of null
    at Table.render (App.js:34)
    at finishClassComponent (react-dom.development.js:8377)
    at updateClassComponent (react-dom.development.js:8345)
    at beginWork (react-dom.development.js:8966)
    at performUnitOfWork (react-dom.development.js:11798)
    at workLoop (react-dom.development.js:11827)
    at HTMLUnknownElement.callCallback (react-dom.development.js:104)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:142)
    at invokeGuardedCallback (react-dom.development.js:191)
    at replayUnitOfWork (react-dom.development.js:11302)
    at renderRoot (react-dom.development.js:11869)
    at performWorkOnRoot (react-dom.development.js:12422)
    at performWork (react-dom.development.js:12343)
    at performSyncWork (react-dom.development.js:12320)
    at requestWork (react-dom.development.js:12220)
    at scheduleWorkImpl (react-dom.development.js:12095)
    at scheduleWork (react-dom.development.js:12055)
    at scheduleRootUpdate (react-dom.development.js:12683)
    at updateContainerAtExpirationTime (react-dom.development.js:12711)
    at Object.updateContainer (react-dom.development.js:12730)
    at ReactRoot../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render (react-dom.development.js:16030)
    at react-dom.development.js:16449
    at Object.unbatchedUpdates (react-dom.development.js:12530)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:16445)
    at Object.render (react-dom.development.js:16513)
    at Object../src/App.js (App.js:51)
    at __webpack_require__ (bootstrap e37a71bbed3a8bfb78c4:678)
    at fn (bootstrap e37a71bbed3a8bfb78c4:88)
    at Object../src/index.js (index.css?f255:26)
    at __webpack_require__ (bootstrap e37a71bbed3a8bfb78c4:678)
    at fn (bootstrap e37a71bbed3a8bfb78c4:88)
    at Object.0 (registerServiceWorker.js:117)
    at __webpack_require__ (bootstrap e37a71bbed3a8bfb78c4:678)
    at bootstrap e37a71bbed3a8bfb78c4:724
    at bootstrap e37a71bbed3a8bfb78c4:724
render @ App.js:34
finishClassComponent @ react-dom.development.js:8377
updateClassComponent @ react-dom.development.js:8345
beginWork @ react-dom.development.js:8966
performUnitOfWork @ react-dom.development.js:11798
workLoop @ react-dom.development.js:11827
callCallback @ react-dom.development.js:104
invokeGuardedCallbackDev @ react-dom.development.js:142
invokeGuardedCallback @ react-dom.development.js:191
replayUnitOfWork @ react-dom.development.js:11302
renderRoot @ react-dom.development.js:11869
performWorkOnRoot @ react-dom.development.js:12422
performWork @ react-dom.development.js:12343
performSyncWork @ react-dom.development.js:12320
requestWork @ react-dom.development.js:12220
scheduleWorkImpl @ react-dom.development.js:12095
scheduleWork @ react-dom.development.js:12055
scheduleRootUpdate @ react-dom.development.js:12683
updateContainerAtExpirationTime @ react-dom.development.js:12711
updateContainer @ react-dom.development.js:12730
./node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:16030
(anonymous) @ react-dom.development.js:16449
unbatchedUpdates @ react-dom.development.js:12530
legacyRenderSubtreeIntoContainer @ react-dom.development.js:16445
render @ react-dom.development.js:16513
./src/App.js @ App.js:51
__webpack_require__ @ bootstrap e37a71bbed3a8bfb78c4:678
fn @ bootstrap e37a71bbed3a8bfb78c4:88
./src/index.js @ index.css?f255:26
__webpack_require__ @ bootstrap e37a71bbed3a8bfb78c4:678
fn @ bootstrap e37a71bbed3a8bfb78c4:88
0 @ registerServiceWorker.js:117
__webpack_require__ @ bootstrap e37a71bbed3a8bfb78c4:678
(anonymous) @ bootstrap e37a71bbed3a8bfb78c4:724
(anonymous) @ bootstrap e37a71bbed3a8bfb78c4:724
Show 5 more frames
index.js:2178 The above error occurred in the <Table> component:
    in Table (at App.js:51)

Consider adding an error boundary to your tree to customize error handling behavior.
__stack_frame_overlay_proxy_console__ @ index.js:2178
logCapturedError @ react-dom.development.js:9627
logError @ react-dom.development.js:9666
commitErrorLogging @ react-dom.development.js:9879
commitAllLifeCycles @ react-dom.development.js:11443
callCallback @ react-dom.development.js:104
invokeGuardedCallbackDev @ react-dom.development.js:142
invokeGuardedCallback @ react-dom.development.js:191
commitRoot @ react-dom.development.js:11578
completeRoot @ react-dom.development.js:12475
performWorkOnRoot @ react-dom.development.js:12425
performWork @ react-dom.development.js:12343
performSyncWork @ react-dom.development.js:12320
requestWork @ react-dom.development.js:12220
scheduleWorkImpl @ react-dom.development.js:12095
scheduleWork @ react-dom.development.js:12055
scheduleRootUpdate @ react-dom.development.js:12683
updateContainerAtExpirationTime @ react-dom.development.js:12711
updateContainer @ react-dom.development.js:12730
./node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:16030
(anonymous) @ react-dom.development.js:16449
unbatchedUpdates @ react-dom.development.js:12530
legacyRenderSubtreeIntoContainer @ react-dom.development.js:16445
render @ react-dom.development.js:16513
./src/App.js @ App.js:51
__webpack_require__ @ bootstrap e37a71bbed3a8bfb78c4:678
fn @ bootstrap e37a71bbed3a8bfb78c4:88
./src/index.js @ index.css?f255:26
__webpack_require__ @ bootstrap e37a71bbed3a8bfb78c4:678
fn @ bootstrap e37a71bbed3a8bfb78c4:88
0 @ registerServiceWorker.js:117
__webpack_require__ @ bootstrap e37a71bbed3a8bfb78c4:678
(anonymous) @ bootstrap e37a71bbed3a8bfb78c4:724
(anonymous) @ bootstrap e37a71bbed3a8bfb78c4:724
Show 4 more frames
App.js:34 Uncaught TypeError: Cannot read property 'foo' of null
    at Table.render (App.js:34)
    at finishClassComponent (react-dom.development.js:8377)
    at updateClassComponent (react-dom.development.js:8345)
    at beginWork (react-dom.development.js:8966)
    at performUnitOfWork (react-dom.development.js:11798)
    at workLoop (react-dom.development.js:11827)
    at renderRoot (react-dom.development.js:11858)
    at performWorkOnRoot (react-dom.development.js:12422)
    at performWork (react-dom.development.js:12343)
    at performSyncWork (react-dom.development.js:12320)
    at requestWork (react-dom.development.js:12220)
    at scheduleWorkImpl (react-dom.development.js:12095)
    at scheduleWork (react-dom.development.js:12055)
    at scheduleRootUpdate (react-dom.development.js:12683)
    at updateContainerAtExpirationTime (react-dom.development.js:12711)
    at Object.updateContainer (react-dom.development.js:12730)
    at ReactRoot../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render (react-dom.development.js:16030)
    at react-dom.development.js:16449
    at Object.unbatchedUpdates (react-dom.development.js:12530)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:16445)
    at Object.render (react-dom.development.js:16513)
    at Object../src/App.js (App.js:51)
    at __webpack_require__ (bootstrap e37a71bbed3a8bfb78c4:678)
    at fn (bootstrap e37a71bbed3a8bfb78c4:88)
    at Object../src/index.js (index.css?f255:26)
    at __webpack_require__ (bootstrap e37a71bbed3a8bfb78c4:678)
    at fn (bootstrap e37a71bbed3a8bfb78c4:88)
    at Object.0 (registerServiceWorker.js:117)
    at __webpack_require__ (bootstrap e37a71bbed3a8bfb78c4:678)
    at bootstrap e37a71bbed3a8bfb78c4:724
    at bootstrap e37a71bbed3a8bfb78c4:724

Please tell me how I can render this.

response.json() returns a promise, not the data.

You need to extract the data first.

fetch('/api/requiredUsers')
    .then(response => response.json())
    .then(data => this.setState({ foo: data }));

You are missing another then (response.json() returns a promise)

fetch('/api/requiredUsers')
    .then(response => response.json())
    .then(data => this.setState({ foo: data }));

check if foo is something

             <tbody>
                {this.state.foo && this.state.foo.map(person => (
                    <tr key={person.id}>
                        <th scope="row">{person.id}</th>
                        <td>{person.name}</td>
                        <td>{person.age}</td>
                        <td>{person.number}</td>
                    </tr>
                ))}
                </tbody>

Define the state in the constructor as given below.

constructor(props) {
    super(props);
    this.state = {
       foo:[]
    }
}

This is occurring because in react life cycle, render() loads before componentdidmount() and foo is not defined before componentdidmount() runs. So there is no state named foo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM