4

Here is my code:

export class App extends Component {
    constructor(props) {
        super(props)
    }
    async fetchSport(sport) {
        let headers = new Headers()
        headers.append('key-goes-here', 'pass-goes-here')
        headers.append('Accept', 'application/json')
        let request = new Request('api-url-goes-here' + sport, {headers: headers})
        let data = await fetch(request).then(response => response.json()).then(json => json.players.forward)
        console.log(data) // 'Christopher Brown'
        return data
    }
    render() {
        return (
            <div className='app'>
                <SportPlayers
                    sport={this.fetchSport('soccer')}
                />
            </div>
        )
    }
}

Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons. Check the render method of `SportPlayers`.

I am trying to figure out why this error is showing. The fetchSport function should be returning a string (like console.log suggests), but it seems like a promise is returned to the view instead.

Bellow is my webpack.config.js:

var webpack = require("webpack");

module.exports = {
    entry: ["babel-polyfill", "./src/index.js"],
    output: {
        path: "/dist/assets",
        filename: "bundle.js",
        publicPath: "assets"
    },
    devServer: {
        inline: true,
        contentBase: "./dist",
        port: 3000 
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                loader: ["babel-loader", 'babel-loader?presets[]=es2016,presets[]=stage-3,presets[]=react'],
            },
            {
                test:  /\.json$/,
                exclude: /(node_modules)/,
                loader: ["json-loader"]
            },
            {
                test: /\.css$/,
                loader: 'style-loader!css-loader!autoprefixer-loader'
            },
            {
                test: /\.scss$/,
                loader: 'style-loader!css-loader!autoprefixer-loader!sass-loader'
            }
        ]
    }
}
5
  • Don't call a fetch method from render. Also, fetchSport returns a promise, which you cannot pass to SportPlayers Commented Apr 4, 2017 at 16:06
  • 1
    Async functions always returns a promise; that's what async functions are for. Commented Apr 4, 2017 at 16:07
  • that's the danger of using async await, people often think they are writing synchronous code, in fact async await enables you to write asynchronous code the same way you would write synchronous code. Maybe you should start by learning how es6 generators works to fully understand the concept of async await Commented Apr 4, 2017 at 16:09
  • By the way the data you return at the end of your function would be reachable with this code this.fetchSport('soccer').then(data => console.log(data)) Commented Apr 4, 2017 at 16:13
  • @Bergi @Frxstrem @oliv37 Thanks all of you. I did not notice async functions always return a promise. So, can I still use fetch in this case? What is the correct context to invoke it. I am new to React. Commented Apr 4, 2017 at 16:47

1 Answer 1

5

As many people have said already, an async function will always return a Promise object, whose value you can then obtain by using .then().

In general, if you need to make many requests to a server, you should be using a state management framework such as Redux. However, Redux introduces a lot of boilerplate. If your usecase is simple, you could just use local UI state to store the result of your call.

Something like this:

export class App extends Component {
    constructor(props) {
      super(props)
      this.state = { sport: '' }
    }

    componentDidMount() {
      this.fetchSport('soccer').then(sport => this.setState({ sport }))
    }

    async fetchSport(sport) {
        let headers = new Headers()
        headers.append('key-goes-here', 'pass-goes-here')
        headers.append('Accept', 'application/json')
        let request = new Request('api-url-goes-here' + sport, {headers: headers})
        let data = await fetch(request).then(response => response.json()).then(json => json.players.forward)
        console.log(data) // 'Christopher Brown'
        return data
    }

    render() {
        return (
            <div className='app'>
                <SportPlayers
                    sport={this.state.sport}
                />
            </div>
        )
    }
}
Sign up to request clarification or add additional context in comments.

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.