0

I want to create a web-app coding game with react that involves evaluating some user (javascript) input.

  constructor(props) {
    super(props);
    this.state = {
      code: ''
    };
  }

  handleChange(key) {
    return event => this.setState({ [key]: event.target.value });
  }

  funScript() {
    eval(this.state.code);
  }

  anotherScript() {
    console.log("Will this work?");
  }

  render() {
    return (
      <div>
        <input 
          type={"text"}
          value={this.state.code}
          onChange={this.handleChange('code')}
         />
        <button onClick={this.funScript()} >run</button>
      </div>
    );
  }

I was hoping that the text input would be able to evaluate javascript on button press by the user (the user types in this.anotherScript(); and the console logs "Will this work?". Unfortunately, it doesn't work and I suspect its an issue specific to React. As soon as the input box is typed in, it tries to evaluate the string (without the button even being pressed!). See here for an example: https://codesandbox.io/s/54rkp584ll

Anyone have a proper React solution that doesn't break javascript on the first character input (and evaluates the function)?

2 Answers 2

1

When you type

<button onClick={this.funScript()} >run</button>

You are calling this.funScript. Remove the parens and you'll just pass the function like you want. Also, funScript needs to be bound to this for it to work.

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

2 Comments

Hmm.. I found just passing a function that executes this.funScript() inside works without bounding funScript. codesandbox.io/s/54rkp584ll <button onClick={() => {this.funScript()}} >run</button> removing the parentheses didn't work, but I'm guessing because I didn't bound this.funScript
Yeah, creating an arrow function that calls the function is basically binding the function. If you're not familiar with arrow functions and this, you should check it out. It's not super obvious but very helpful/important to understand.
0

Here you have funScript, which evaluates your code with proper context:

class Test {

    // ...

    funScript() {
        const code = ("" + this.state.code).replace(/this/ig, "__self__");
        const execute = new Function("__self__", code);
        execute(this);
    }

    // ...
}

3 Comments

Is this making the "this." unnecessary in the executed string of code? Useful, but I'm not sure it addressed the issue. Also, I'm not familiar with the new Function syntax, but I'll look into it
To evaluate method from the component Test, you have to pass a context manually. If it's not necessary, you can skip the code with this/self. The good point in this code is that you can redefine window, document and other global objects, which can be a huge security improvement.
I'm not as concerned with Security (since its front-end, which shouldn't contain the secure info for my purpose, except perhaps the session token...) as I am with sandboxing the code so I can interrupt the execution of user-written code which causes errors and infinite loops, etc... but this seems like it could possibly help with the sandboxing?

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.