0

I get Cannot read property 'callToPrayer' of undefined

import { adhaan } from './assets/audio.js'

export default class JustPrayClient extends Component {
  constructor (props) {
    super(props)
    // this.props = props   
    this.playSound.bind(this)
  }

  playSound () {
    // console.log(this.props.test)
    this.props.callToPrayer.play() //why is props undefined here?
  }

  render () {
    return (
      <View style={styles.container}>
        <Text onPress={this.playSound} style={styles.welcome}>
          Welcome to React Native! {this.props.test}
        </Text>
      </View>
    )
  }
}

const Main = () => <JustPrayClient callToPrayer={adhaan} test='hello' />

Does this have something to do with the this context?
If so, I don't know where/how I should bind this...

abooayoob
  • 91
  • 2
  • 7

2 Answers2

2

You are not binding playSound function correctly in the constructor. You need to assign it back to the function like

this.playSound = this.playSound.bind(this)

Try this and it should fix you problem. However if you are using webpack and correctly specifying the presets in the module loaders then, binding with arrow functions also functions correclty

playSound = () = > {
   console.log(this.props.callToPrayer);
}

Also check if play() function is getting available to the playSound function once you console.log() it and if it is available then you can use it.

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
1

you have two choices:

.bind in constructor

  constructor (props) {
    super(props);
    this.playSound = this.playSound.bind(this);
  }

OR

use Arrow Function to define playSound

  playSound = () => {
    this.props.callToPrayer.play();
  }
yadhu
  • 15,423
  • 7
  • 32
  • 49
  • Do mean `const playSound = () => { ... }`? – Andrew Li Nov 25 '16 at 01:08
  • No. It should be the same way your constructor function and render function looks like (but just use arrow syntax). – yadhu Nov 25 '16 at 01:10
  • Oh stupid me, I was not binding correctly in my constructor! Thanks a lot! – abooayoob Nov 25 '16 at 01:11
  • @free-soul but you are assigning a variable, you need const, let or var? – Andrew Li Nov 25 '16 at 01:13
  • @AndrewLi, no we don't use keywords for defining methods in [ES6 classes](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes), except [`static`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static). – yadhu Nov 25 '16 at 01:25
  • @free-soul But that's not a method? It's a variable holding an arrow function? It's equivalent to a function expression. You need `const blah = ...` – Andrew Li Nov 25 '16 at 01:26
  • Yeah it seems the arrow function thing does not work inside a class like that. – abooayoob Nov 25 '16 at 01:26
  • http://stackoverflow.com/questions/31362292/how-to-use-es6-arrow-in-class-methods – yadhu Nov 25 '16 at 01:33
  • @free-soul Yes, that's an experimental thing with Babel, but currently you must define it as a variable of the class. – Andrew Li Nov 25 '16 at 01:45
  • Yes that's a highly experimental feature (but we still have it if we use presets) to directly put the assignment in the class scope.. But of course you cannot use a keyword `const` or `let` for defining class properties outside constructor (Na! even using `const` inside constructor doesn't become a class property). "There is (intentionally) no direct declarative way to define either prototype data properties (other than methods) class properties, or instance property". More reading http://wiki.ecmascript.org/doku.php?id=strawman:maximally_minimal_classes – yadhu Nov 25 '16 at 02:14