1

I'm getting an error when I try to bind values to the component function handleInput: Uncaught TypeError: Cannot read property 'bind' of undefined

However, when I insert the input element into the return statement at the bottom of the render method, it doesn't produce any errors. I'm guessing that this has something to do with the lifecycle of the render method, but I'm not sure.

Any insight is appreciated.

As for what the code does, it retrieves a string from this.props.info.text and replaces all instances of <= var[0-9] => with an html input box, then appends to a div. On user input, the values are propagated to a parent component.

export default class Line extends React.Component {

 constructor() {
   super();
 }

 handleInput(id, e) {
   console.log(id);
   this.props.handleCode(e.target.value);
 }

 shouldComponentUpdate(){
   if (document.getElementById('otherClass').innerHTML.length == 0){
     return true;
   }
   return false;
 }

 render() {
   var id = this.props.id;
   let codeVal = "";
   let codeDiv = document.createElement('div');
   if (typeof(this.props.info) !== 'undefined') {
     //breaks here
     codeVal = this.props.info.text.replace(/<= var[0-9] =>/, '<input type="text" onInput=this.handleInput.bind(this,id)></input>');
     let index = codeVal.indexOf('<');
     let splits = [codeVal.slice(0, index), codeVal.slice(index)];
     codeDiv.innerHTML = "<div class='row'><div class='col-md-6'>"+splits[0]+"</div><div class='col-md-6'>"+splits[1]+ "</div></div>";
     document.getElementById('otherClass').appendChild(codeDiv);
   }

   return(
     <div id='otherClass'></div>
   );

 }
}

Parent code:

export default class StateVal extends React.Component {
  handleCode(id, e){
    console.log("value propagated on user input");
    alert(e);
  }
  render() {
    return (
     <div className="col-md-6">
       <div className="card-block">
        < Line info={this.props.data.codeBody[0]} handleCode={this.handleCode} id={1} />
     </div>
   </div>
  );
}
}

Edit: the idea is that if I retrieve a text value through props like "int value = <=var0=>" how can I convert it to a responsive html input tag like

 int value = <input type='text' onInput=this.handleInput.bind(this, id)/>

and then render it in html

user2998285
  • 15
  • 1
  • 7
  • 1
    This is.... kinda crazy. Why are you creating elements using the dom api and appending them to your rendered component? Why not just make react components like `
    ` etc?
    – azium May 17 '16 at 19:35
  • The html is supposed to be dynamic. That's why I used regex and can't just return a normal div. Here's an example prop text value: int value = <= var0 => I'm supposed to convert it to int value = – user2998285 May 17 '16 at 19:44
  • 2
    Are you able to post the parent code? This is an ugly hack and I don't think this approach is going to work, if you could provide more information about the requirements you might get a better answer. – pgraham May 17 '16 at 20:01
  • I agree with the other two. I'm not sure the dynamic you're trying to accomplish, but I'm sure it's something easily do-able with React. Also, you should use JSX to inject a function within React component. – Yuya May 17 '16 at 20:11
  • 1
    @user2998285 everything in React is just JavaScript! And JavaScript is about as dynamic as it gets. Just render components based on state and props. Don't bother touching the DOM api whatsoever. – azium May 17 '16 at 20:51
  • You cannot create DOM elements from within the `render` function. That’s just not how it works. If you need to manipulate the DOM manually, use the component lifecycle events. – poke May 17 '16 at 21:32
  • https://medium.com/@john1jan/react-binding-revealed-aa458df8c136#.fd5z0vmjl – John Mar 23 '17 at 10:49

3 Answers3

1

You can only write valid HTML when generating Html from a string with react.

<input type='text' onInput=this.handleInput.bind(this, id)/> is not valid: onInput is not a HTML valid props

Generating a jsx string to HTML with react is a special case requiring babel.

I don't think you'll be able to insert jsx string in a component on the fly using a string but there is may be another solution. Split your string into an array and replace matching string by not a string code "<../>" but by a jsx element <...>. This jsx element will have the function binding as wanted to your component. I found a similar solution here: Replace part of string with tag in JSX

Community
  • 1
  • 1
Damien Leroux
  • 11,177
  • 7
  • 43
  • 57
0

There is a proper way to render a string with react:

Use dangerouslySetInnerHTML to inject HTML as a string in React. Subject is treated here

Regards

Community
  • 1
  • 1
Damien Leroux
  • 11,177
  • 7
  • 43
  • 57
  • Thanks, I guess I wasn't really clear on my question, but the issue isn't simply just rendering the html, but also to ensure that handleInput is bound to 'this' and 'id.' That's where I'm having trouble. I keep getting errors saying that handleInput is not defined, or cannot read property 'bind' of undefined. – user2998285 May 17 '16 at 21:02
0

You can set the bind key word at the end like below instead of the example you have given.

onInput=this.handleInput(id).bind(this)

or just call this method here and bind it at the constructor level.

onInput=this.handleInput(id)

constructor() {
   super();
   this.handleInput=this.handleInput.bind(this);
 }
Thanigainathan
  • 1,505
  • 14
  • 25