0

trying to change string variable from React.Children.map, then React.cloneElement to change the color. I have a Title on my homepage. I want to update node color of each character within the title string. Trying to do it this way, but getting en error of : Cannot read property 'colorString' of undefined

const LetterStyle = React.createClass({
  colorString: function(value){
    this.setState({color: "green"});
  },

  render: function(){
    const colorArray = []
    var childrentWithProps = React.Children.forEach(this.props.children, (child, i) => {
      for (var i=0; i<child.length; i++){
        return React.Children.map(child[i], function(content, i) {
          if(content !== " "){
            React.cloneElement(content, { colorString: this.colorString })
          }
        });
      }
    })

    return(
      <h1 className="lead" ref="lead">
        <span>{childrentWithProps}</span>
      </h1>
    );
  }

});
Pineda
  • 7,435
  • 3
  • 30
  • 45

2 Answers2

0

It looks like you are losing the this reference by the time you get to the line React.cloneElement(content, { colorString: this.colorString })

Try to define var that = this; right after the render function() { like

  render: function()
    {
      var that = this;
      const colorArray = [] to preserve the properties of `this`.

and change the line to React.cloneElement(content, { colorString: that.colorString })

Also, I would suggest reading the differences between let, var, and const. In ES6 syntax, var is generally unnecessary, and mixing it with const and let can get confusing. Read more about the differences here:

What's the difference between using "let" and "var" to declare a variable?

Community
  • 1
  • 1
Yo Wakita
  • 5,322
  • 3
  • 24
  • 36
0

This is the first time I've seen an implementation of .map and forEach from the React Top-Level API. They differ in their usage from their native JavaScript cousins.

There are a couple of problems with your code.

1st Problem that causes your error:

The docs for the latter state that React.Children.map and React.Children.forEach take two arguments, the first being a keyed fragment or array of children and the second being a callback whose only argument is the value that this will be set to within the React.Children.forEach and React.Children.map calls. Their signatures are as follows:

React.Children.forEach(children, function[(thisArg)])

React.Children.map(children, function[(thisArg)])

The solution then is to not pass in to arguments but one into either call in order to remove your error.

As an example, your resulting .map call would look like this:

return React.Children.map(child[i], function(this){
  if (content !== " "){
    React.cloneElement(content, { colorString: this.colorString });
  }
});

2nd problem worth mentioning:

You have used forEach here which will effectively iterate over the this.props.children array.

Inside it you are referencing the current value being iterated over childand are running a for loop over that element to in turn get to your .map call.

This doesn't look correct for your application here as child most likely represents a single component or React element rather than an array to be looped over again.

Solution: use the for loop or the forEach here, but not both

Pineda
  • 7,435
  • 3
  • 30
  • 45