Creating Complex Components

In a previous article, we learned about components and all the awesome things that they do. We learned that components are the primary ways through which React allows our visual elements to behave like little reusable bricks that contain all of the HTML, JavaScript and styling needed to run themselves. Beyond reusability, there is another major advantage components bring to the table. They allow for composability. You can combine components to create more complex components.


This is a companion discussion topic for the original entry at http://www.kirupa.com/react/creating_complex_components.htm

Outstanding tutorial, outstanding writing.

You have by far the best tutorials for the React beginner that Iā€™ve found. Keep up the great work!

Thanks, Finnegan! Glad you find them useful. If there are additional topics that you would like me to cover, please let me know :slight_smile:

Very good tutorial.
Iā€™m stumbling on behavior I canā€™t explain.
If Iā€™m using the following code, I see the square


	var Square = React.createClass({
		render: function() {
			
			return(
				<div>
			
				</div>
			);
		}
	});
	var Card = React.createClass({
	  	render: function() {
	      	var cardStyle = {
		        height: 200,
		        width: 150,
		        padding: 0,
		        backgroundColor: "#FFF",
		        WebkitFilter: "drop-shadow(0px 0px 5px #666)",
		        filter: "drop-shadow(0px 0px 5px #666)"
	        };
		    return (
		 		<div style={cardStyle}>
					
        		</div>
		    );
	    }
	});

	ReactDOM.render(
	<div>
		<Card/>
  	</div>,
  	document.querySelector("#container")
	);
</script>
</body>

However, If I use this code (omitting the Div in the square class), I see nothing


	var Square = React.createClass({
		render: function() {
			
			return(
			
			);
		}
	});
	var Card = React.createClass({
	  	render: function() {
	      	var cardStyle = {
		        height: 200,
		        width: 150,
		        padding: 0,
		        backgroundColor: "#FFF",
		        WebkitFilter: "drop-shadow(0px 0px 5px #666)",
		        filter: "drop-shadow(0px 0px 5px #666)"
	        };
		    return (
		 		<div style={cardStyle}>
					
        		</div>
		    );
	    }
	});

	ReactDOM.render(
	<div>
		<Card/>
  	</div>,
  	document.querySelector("#container")
	);
</script>
</body>

Why the Div matter if I do not reference the Square class at all?

Regards,
N.

The reason has to do with JSX being turned into regular JavaScript without knowing what code will be hit or not. When the Babel transpiler runs, it turns your first version of your code into this:

var Square = React.createClass({
	displayName: "Square",

	render: function render() {

		return React.createElement("div", null);
	}
});

When you donā€™t specify anything to return, you get an error because the render method must call React.createElement. Not having anything there causes an error like Unexpected Token or something equivalent.

:slight_smile:

And in fact you can work around this by slightly modifying the example (and supporting prose) like this:

var Square = React.createClass({
	render: function() {
		
		return;
	}
});

As you can see I simply omited the parenthetical marks after the return which was empty context. Tested on both Chrome and electron (Chromium.) After doing this it transpiles and executes a-ok allowing you to check your work as you go rather than ā€˜all at the end.ā€™

1 Like

Hello, here is the code in between my script tags that I have and nothing is displaying. I have read and reread the example and explanation in the tutorial, but still canā€™t get it to work. Is there anything you can see here that would help point me in the right direction? I want to complete the tutorial but canā€™t get passed this stage. Help!

var Square = React.createClass({
render: function(){

var = squareStyle = {
	heght: 150,
	backgroundColor: this.props.color

}

};

return(
<div style={squareStyle}></div>
);

}

});



var Label = React.createClass({

render: function() {

var labelStyle = {
      fontFamily: "sans-serif",
      fontWeight: "bold",
      padding: 13,
      margin: 0
	  
return(
<p style={labelStyle}>{this.props.color}</p>
);

}

});



var Card = React.createClass({

render: function() {
var cardStyle = {
        height: 200,
        width: 150,
        padding: 0,
        backgroundColor: "#FFF",
        WebkitFilter: "drop-shadow(0px 0px 5px #666)",
        filter: "drop-shadow(0px 0px 5px #666)"
      };
return(
<div style={cardStyle}>
	
	<Square color={this.props.color}/>
    <Label color={this.props.color}/>
	</div>
);

}

});



ReactDOM.render(
      <div>
      <Card color="FF6699"/>
      </div>,
      document.querySelector("#container")
    );

Is your console showing any errors? I donā€™t access to a laptop right now, but I can check in more detail tomorrow :slight_smile:

Iā€™ll look at this code again soon and get back to you. I appreciate your quick response. Thx!

Hi, there was an error, and I watched the video and worked through it. Thx! But I have into another snag in the ā€œDealing with Stateā€ section. There is another unexpected error in the console. I see the carrot, but donā€™t understand what exactly is the issue. I have the same exact code in the example. Can you point me in the right direction?

/////
class LightningCounter extends React.Component {
                constructor(props, context) {
                    super(props, context);
                     
                    this.state = {
                        strikes: 0
                    };
 
                    this.timerTick = this.timerTick.bind(this);
                }
 
                timerTick = () => {
                    this.setState({
                        strikes: this.state.strikes + 100
                    });
                }
 
                componentDidMount() 
                {
                    setInterval(this.timerTick, 1000);
                }
                 
                render() {
                    var counterStyle = {
                        color: "#66FFFF",
                        fontSize: 50
                    };
 
                    var count = this.state.strikes.toLocaleString();
 
                    return (
                        <h1 style={counterStyle}>{count}</h1>
                    );
                }
            }
 
            class LightningCounterDisplay extends React.Component {
                render() {
                    var commonStyle = {
                        margin: 0,
                        padding: 0
                    };
 
                    var divStyle = {
                        width: 250,
                        textAlign: "center",
                        backgroundColor: "#020202",
                        padding: 40,
                        fontFamily: "sans-serif",
                        color: "#999999",
                        borderRadius: 10
                    };
 
                    var textStyles = {
                        emphasis: {
                            fontSize: 38,
                            ...commonStyle
                        },
                        smallEmphasis: {
                            ...commonStyle
                        },
                        small: {
                            fontSize: 17,
                            opacity: 0.5,
                            ...commonStyle
                        }
                    }
 
                    return(
                        <div style={divStyle}>
                            <LightningCounter/>
                            <h2 style={textStyles.smallEmphasis}>LIGHTNING STRIKES</h2>
                            <h2 style={textStyles.emphasis}>WORLDWIDE</h2>
                            <p style={textStyles.small}>(since you loaded this example)</p>
                        </div>
                    );
                }
            }
 
            ReactDOM.render(
                <LightningCounterDisplay/>,
                document.querySelector("#container")
            )

////

Can you copy and paste the error from the console? :slight_smile:

Here you go! Thx again!

Uncaught SyntaxError: embedded: Unexpected token (13:26)
  11 |                 }
  12 |  
> 13 |                 timerTick = () => {
     |                           ^
  14 |                     this.setState({
  15 |                         strikes: this.state.strikes + 100
  16 |                     });

I made a mistake when specifying the current syntax for timerTick. Try this instead:

timerTick() {
    this.setState({
        strikes: this.state.strikes + 100
    });
}

Canā€™t seem to see the card for some reason. Can you help see if there is any error in my code or dependencies or whatever please:

<!DOCTYPE html >
<html lang = "en" >
    <head >
        <meta charset = "UTF-8" >
        <meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
        <meta http - equiv = "X-UA-Compatible" content = "ie=edge" >
        <title> More Components </title> 

        <script src = "https://unpkg.com/react@16/umd/react.development.js" > </script> 
        <script src = "https://unpkg.com/react-dom@16/umd/react-dom.development.js" > </script> 
        <script src= "https://unpkg.com/babel-standalone@6/babel.min.js" > </script>

        <style> 
            #container {
                padding: 50 px;
                background - color: #FFF;
            } 
        </style> 
    </head>

    <body >
        <div id = "container" >
        
        </div>
        
        <script type = "text/babel" >
            

            var Square = React.createClass({
              render: function() {
                return (
                  <div/>
                );
              }
            });


            var Label = React.createClass({
              render: function() {
                return (
                  <div/>
                );
              }
            });


            var Card = React.createClass({
              render: function() {
                var cardStyle = {
                  height: '200px',
                  width: '150px',
                  padding: 0,
                  backgroundColor: '#FFF',
                  WebkitFilter: 'drop-shadow(0px 0px 5px #666)',
                  filter: 'drop-shadow(0px 0px 5px #666)'
                };
                return (
                  <div style= {cardStyle}>

                  </div>
                );
              }
            });


            var destination = document.querySelector('#container');

            ReactDom.render(
                <div>
                  <Card/>
                </div>,
                destination
            );
        </script> 
    </body>
</html>

My inspect console error is the following:

Uncaught TypeError: React.createClass is not a function

You have to use the class syntax as opposed to React.createClass, starting with React 16. The code in the tutorial should work for you, for it is using the latest syntax! The video isnā€™t updated yet, but that is something I will try to re-record later this week :slight_smile:

Would you post a blog or notify us followers when you do update the videos please. Many thanks,

Good stuff man this book has been helpful and greatly appreciated.

1 Like

Thanks! Glad you enjoyed it :slight_smile: