3

I bundle the codes with ./node_modules/.bin/webpack -d. I didn't compile ES6 to ES5 except this class fields proposal.

It give this error:

Uncaught TypeError: this.fetchTestExecutions is not a function

Here's the codes:

import React from 'react'
import Config from 'Config'

class HomePage extends React.Component {

  state = {
    executions: this.fetchTestExecutions()
  }

  fetchTestExecutions = () => {
    const host = Config.host
    return fetch(`${host}/execution/index`)
      .then(response => response.json())
      .then(json => {
        this.setState({executions: json})
      })
  }

  render() {
    return(
      <div>
        { this.state.executions.map(x => <div>x.from</div>) }
      </div>
    )
  }
}

export default HomePage

Here's the webpack.config.js:

var webpack = require('webpack')

module.exports = {
  entry: './src/App.jsx',
  output: {
    filename: './../public/bundle.js'
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'babel-loader',
        query: {
          plugins: ['transform-class-properties'],
          presets: ['react'],
        }
      }
    ]
  },
  externals: {
    'Config': JSON.stringify({host: "http://127.0.0.1:3000"})
  }
}

What's wrong?

Thanks for your time!

3 Answers 3

3

Setting a method (specially an api call) as a state property is not a good pattern. Instead, prefer calling the api first in a lifecycle event and then set state later.

class HomePage extends React.Component {
  state = {
    executions: []
  }

  componentDidMount() {
    const host = Config.host

    fetch(`${host}/execution/index`)
      .then(response => response.json())
      .then(json => this.setState({ executions: json }))
  }

  render() {
    return(
      <div>
        { this.state.executions.map(x => <div>x.from</div>) }
      </div>
    )
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

He's not setting the method, he's setting the promise returned from that method. However, it's definitely a very bad pattern.
Yes, sure. It was just a mean to explain the bad pattern :)
Hi @mersocarlin, thanks for the advise on setting state. what if I got another randomString = () => "a string", and state = { executions: this.randomString()}. It still give the same error. state is a class variable? this.randomString() is instance method?
@mCY state is an object link to docs. And I wouldn't use method (as randomString for example) to set its initial properties. this.randomString() is an instance method if you defined it inside your component (which allows you to call this.randomString()) from anywhere within the component.
2

Class fields (which are currently stage 2 proposal) are assigned on class instantiation. The original code is equal to this ES6 code:

class HomePage extends React.Component {
  constructor() {
    this.state = {
      executions: this.fetchTestExecutions()
    };

    this.fetchTestExecutions = () => { /*...*/ };
  }
  ...
}

As it appears, the order matters, and fetchTestExecutions is undefined at the moment when it's being called.

In order to make it work, fetchTestExecutions class field should be defined before state.

Unless fetchTestExecutions is used as a callback (and it's not), it should definitely be prototype method (already suggested in another answer):

class HomePage extends React.Component {
  state = {
    executions: this.fetchTestExecutions()
  }

  fetchTestExecutions() { /*...*/ }
  ...
}

This eliminates the problem and results in more efficient code. See also this explanation on what are the practical differences between arrow (instance) and prototype methods.

Comments

1

You have to change your function like this

fetchTestExecutions(){
const host = Config.host
return fetch(`${host}/execution/index`)
  .then(response => response.json())
  .then(json => {
    this.setState({executions: json})
  })
}

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.