0

Objective: When my Game component receives a prop I want componentDidUpdate() to call a function called consolelog which is a child of another function called gamecode().

Problem: using this.gameCode.consolelog() always returns an error saying that consolelog is not a function of gameCode.

Note: Gamecode() is imported into my react component (Game) from a file called gamecode.js

Component:

import React, {Component} from 'react';

import {gameCode, showLeaderboard} from '../utility/gamecode';

class Game extends Component{
  constructor(props){
    super();
    this.state = {
      drawL : null
    }
  };

  componentDidMount(){
    this.gameCode();
  };

  componentDidUpdate(){
    //will run when the state changes
    if(this.props.leaderboard){
        var a = this.props.leaderboard;
        this.gameCode.consolelog(a);
    }
  }   

  render(){
    return(
      <div className="Game">
        <canvas id="canvas"></canvas>
        <button onClick={this.props.getleaderboard} className="showleaders">Show leaderboard</button>
      </div>
    );
  }
}

export default Game;

GameCode.js function:

gameCode(){
  //the main function initializes some stuff immediately and start running the update() and draw() functions
  const canvas = document.getElementById('canvas');
  canvas.width = 800;
  canvas.height= 600;
  const ctx = canvas.getContext("2d");
  const FPS = 30;
  setInterval(() => {
      update();
      draw();
  }, 1000/FPS);

  //but sometimes I need to call other functions on demand, but these functions depend on what the parent function and other sibling functions
  function consolelog(a){
    console.log("success!");
    console.log(a);
  }
}
2
  • Why "a child of another function"? Why can't you just export consolelog as its own function, and import it into your module? Commented Sep 9, 2017 at 21:20
  • The reason I don't want to do that is because I have other subfunctions that rely on variables/functions that are scoped to GameCode(). This is a canvas html game and so I have subfunctions called update and draw that draw to the canvas and I don't want multiple functions drawing to it. Commented Sep 9, 2017 at 21:26

3 Answers 3

2

Your Game class doesn't have a gameCode method so you can't use this.gameCode inside any of it's methods.

If you imported the gameCode inside the js file, you can use it anywhere inside:

componentDidMount(){
    gameCode();
};

The problem here is that the function gameCode in your example doesn't do anything - it only define a new function (locally) every time you call it. It's not an object that you can use to call it's function...

If gameCode was an object, you could have use:

gameCode.consolelog(something);

but it's not

You can change the gameCode to something like that:

export default gameCode = {
    consolelog: function (a){
        console.log("success!");
        console.log(a);
    }
}

And now since gameCode is an object, with the consolelog attribute as a function, you can use gameCode.consolelog(...) inside your Game class.

Sign up to request clarification or add additional context in comments.

13 Comments

I think we're going in the right direction here but to note gameCode() does run some code on it's own. I just didn't include it in my question because it's a lot of code. Here is the code and most of my subfunctions depend on these initializations: const canvas = document.getElementById('canvas'); canvas.width = 800; canvas.height= 600; const ctx = canvas.getContext("2d"); const FPS = 30; setInterval(() => { update(); draw(); }, 1000/FPS); function consolelog(a){ console.log("success!"); console.log(a); }
Please update the original question with the code. It's impossible to read code in comments.
So as explained in the second part of my answer - when you call the gameCode - you define a local function (by the name consolelog) but that function is not accessible...
Is there any way to access it?
Sure. Check my answer, it's all there :)
|
1

You could use something along the lines of a revealing module pattern. Keep private variables in scope to gameCode and export the public vars and functions that you need.

const gameCode = (function () {

  const a = 1;

  function consolelog() {
    console.log(`success${a}`);
  }

  return {
    consolelog: consolelog
  }

});

export default gameCode;

In your other file:

import gameCode from './gameCode';

componentDidMount() {
  const gc = gameCode();
  gc.consolelog(); // success1
}

DEMO

13 Comments

all my consts and variables come back as undefined when I use your method, but only when I wrap the const a = 1 in an init function
You don't need to put it in an init function. What's the reason for doing so?
Well for some reason when I don't put it into an init function,the canvas const that I define one line above canvas.width = 800; shows up as undefined... not sure why querySelector can no longer find it.
ahh I figured out what was causing the bug. The () at the end of the gamecode.js file was causing it to run as soon as I imported it which was before the canvas rendered.
Pass them in like normal function parameters - gc.consolelog(this.props)?
|
0

First of all, you don;t need to call it with the this key word once you imported it. You just call it that way: gameCode();.
Second, you are not returning anything from this function, hence you can't access it's nested function.
I think you need to re think the way you expose objects and functions.
For example, GameCode.js can look like this:

 const consolelog = function (a){
    console.log("success!");
    console.log(a);
 }
 export consolelog;

And then import it in your component:

import {consolelog} from '../utility/gamecode';

Edit
As a followup to your comment, if you need a function that will nest other functions and variables then you can create a class;

class GameCode {
  constructor(){
    this.consolelog = this.consolelog.bind(this);
  }

  consolelog(a){
      console.log("success!");
      console.log(a);
  }
}
export default GameCode;  

Then import it in you Component:

import GameCode from '../utility/gamecode'; // notice the import for default exports

5 Comments

The reason I don't want to do that is because I have other subfunctions that rely on variables/functions that are scoped to GameCode() This is a canvas html game and so I have subfunctions called update and draw that draw to the canvas and I don't want multiple functions drawing to it.
then create a class
I don't know anything about classes, how would a class help here?
that's odd, you are using a class in the code you posted :)
Well that's just because I wanted a class based component so that I can work with props and state. That's as far as my knowledge of classes go. Anyways, what I need to be able to do is have my component run gameCode which then initializes a bunch of variables/consts and then runs some functions immediately. Then sometimes I need to be able to call some of it's sub functions as needed. So I'm not sure if turning gameCode into a class is the answer here.

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.