\n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1170","displayCommentEventSequenceNumber":1170},{"id":"commentId-4","developerGroupId":"devGroupId-2","timestamp":1612643465624,"commentText":"The render method takes two parameters. The first is a React generated element. There is an object called React in the library that has a method that will dynamically create an html element for me.","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"React.createElement(","startRow":20,"startColumn":16,"endRow":20,"endColumn":36,"selectedTextEventIds":["ev-875","ev-876","ev-877","ev-878","ev-879","ev-880","ev-881","ev-882","ev-883","ev-884","ev-885","ev-886","ev-887","ev-888","ev-889","ev-890","ev-891","ev-892","ev-893","ev-894","ev-899"]},{"fileId":"fileId-0","selectedText":")","startRow":20,"startColumn":62,"endRow":20,"endColumn":63,"selectedTextEventIds":["ev-897","ev-928"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"12","linesBelow":"4","currentFilePath":"/index.html","viewableBlogText":" \n
\n
\n \n
\n
\n \n \n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1170","displayCommentEventSequenceNumber":1170},{"id":"commentId-5","developerGroupId":"devGroupId-2","timestamp":1612643535823,"commentText":"The second parameter to the render method is where the element should go. I am using the built-in document object's getElementById method to retrieve the div I defined in the html. The new element will be placed inside the div with the id app.","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"document.getElementById(\"app\") ","startRow":21,"startColumn":16,"endRow":21,"endColumn":47,"selectedTextEventIds":["ev-947","ev-948","ev-949","ev-950","ev-951","ev-952","ev-953","ev-954","ev-955","ev-956","ev-957","ev-958","ev-959","ev-960","ev-961","ev-962","ev-963","ev-964","ev-965","ev-966","ev-967","ev-968","ev-969","ev-970","ev-974","ev-976","ev-977","ev-978","ev-975","ev-973","ev-861","ev-862"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"13","linesBelow":"3","currentFilePath":"/index.html","viewableBlogText":" \n
\n
\n \n
\n
\n \n \n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1170","displayCommentEventSequenceNumber":1170},{"id":"commentId-6","developerGroupId":"devGroupId-2","timestamp":1612643648050,"commentText":"The React object's createElement method takes three parameters:
- the type of element that the react library should create (in this case an h1)
- an object of attributes to set on the element (I am not adding any attributes to the h1 yet)
- one or more child elements (in other words, all of the things to put in the h1, I am adding some text)
","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"\"h1\", {}, \"Hello World!!!\"","startRow":20,"startColumn":36,"endRow":20,"endColumn":62,"selectedTextEventIds":["ev-899","ev-901","ev-902","ev-900","ev-903","ev-904","ev-905","ev-908","ev-909","ev-910","ev-911","ev-913","ev-914","ev-915","ev-916","ev-917","ev-918","ev-919","ev-920","ev-921","ev-922","ev-923","ev-924","ev-925","ev-926","ev-912","ev-897"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"1","linesBelow":"2","currentFilePath":"/index.html","viewableBlogText":" ReactDOM.render( \n React.createElement(\"h1\", {}, \"Hello World!!!\"), \n document.getElementById(\"app\") \n ); ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1170","displayCommentEventSequenceNumber":1170},{"id":"commentId-7","developerGroupId":"devGroupId-2","timestamp":1612643755459,"commentText":"You might be wondering how I am accessing anything from the React library since my project directory only holds this one file. I include a script reference to the React and ReactDOM libraries. This is the simplest way to start using React but it is not very efficient since the page will download the entire library and execute this code every time the page is served.","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":" \n ","startRow":15,"startColumn":8,"endRow":16,"endColumn":80,"selectedTextEventIds":["ev-1005","ev-1006","ev-1007","ev-1008","ev-1009","ev-1010","ev-1011","ev-1012","ev-1013","ev-1014","ev-1015","ev-1016","ev-1017","ev-1018","ev-1019","ev-1020","ev-1021","ev-1022","ev-1023","ev-1024","ev-1025","ev-1026","ev-1027","ev-1028","ev-1029","ev-1030","ev-1031","ev-1032","ev-1033","ev-1034","ev-1035","ev-1036","ev-1037","ev-1038","ev-1039","ev-1040","ev-1041","ev-1042","ev-1043","ev-1044","ev-1045","ev-1046","ev-1047","ev-1048","ev-1049","ev-1050","ev-1051","ev-1052","ev-1053","ev-1054","ev-1055","ev-1056","ev-1057","ev-1058","ev-1059","ev-1060","ev-1061","ev-1062","ev-1063","ev-1064","ev-1065","ev-1066","ev-1067","ev-1068","ev-1069","ev-1070","ev-1071","ev-1072","ev-1073","ev-1074","ev-1075","ev-1076","ev-1077","ev-1078","ev-1079","ev-1080","ev-1081","ev-1082","ev-1083","ev-1084","ev-1085","ev-1086","ev-1087","ev-1088","ev-1089","ev-1090","ev-1091","ev-1092","ev-1093","ev-1094","ev-1095","ev-1096","ev-1097","ev-1098","ev-1099","ev-1100","ev-1101","ev-1102","ev-1103","ev-1104","ev-1105","ev-1106","ev-1107","ev-1108","ev-1109","ev-1110","ev-1111","ev-1112","ev-1113","ev-1114","ev-1115","ev-1116","ev-1117","ev-1118","ev-1119","ev-1120","ev-1121","ev-1122","ev-1123","ev-1124","ev-1125","ev-1126","ev-1127","ev-1128","ev-1129","ev-1130","ev-1131","ev-1132","ev-1133","ev-1134","ev-1135","ev-1136","ev-1137","ev-1138","ev-1139","ev-1140","ev-1141","ev-1142","ev-1143","ev-1144","ev-1145","ev-1146","ev-1147","ev-1148","ev-1149","ev-1150","ev-1151"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"7","linesBelow":"8","currentFilePath":"/index.html","viewableBlogText":" \n
\n
\n \n
\n
\n \n \n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1170","displayCommentEventSequenceNumber":1170},{"id":"commentId-8","developerGroupId":"devGroupId-2","timestamp":1612643857416,"commentText":"If you use your browser to open this html file with control-O (windows) or command-O (mac) you should see an identical page that is in the attached screenshot.

You can see that React injected an h1 with the text \"Hello World!!!\" in the div with the id of \"app\". It did this because the ReactDOM.render method went and found the div and created an h1 element to put inside of it.

Note: I am using Firefox in this example because Chrome does not allow you to run a React app like this when it is served from the file system. Firefox does allow it. In future React playbacks I'll use a server to serve the files.
","selectedCodeBlocks":[],"imageURLs":["/media/images/pb617-1612643797062-image.png"],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"0","currentFilePath":"/index.html","viewableBlogText":"","commentTags":["image"],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1170","displayCommentEventSequenceNumber":1170}],"ev-1192":[{"id":"commentId-9","developerGroupId":"devGroupId-2","timestamp":1612644054514,"commentText":"The second parameter to createElement is an object where you can specify some attributes to the element being created. Here I add the bootstrap class display-4 to the h1 that is being created. The attached screenshot shows the new, more modern looking h1.

Note: since this is javascript code the html attribute class cannot be used because it is a javascript keyword. Instead, use className when specifying an html class like this.
","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"{className: \"display-4\"}","startRow":20,"startColumn":42,"endRow":20,"endColumn":66,"selectedTextEventIds":["ev-905","ev-1171","ev-1172","ev-1173","ev-1174","ev-1175","ev-1176","ev-1177","ev-1178","ev-1179","ev-1180","ev-1181","ev-1182","ev-1183","ev-1184","ev-1185","ev-1186","ev-1187","ev-1188","ev-1189","ev-1190","ev-1191","ev-1192","ev-908","ev-909"]}],"imageURLs":["/media/images/pb617-1612643933557-image.png"],"videoURLs":[],"audioURLs":[],"linesAbove":"1","linesBelow":"2","currentFilePath":"/index.html","viewableBlogText":" ReactDOM.render( \n React.createElement(\"h1\", {className: \"display-4\"}, \"Hello World!!!\"), \n document.getElementById(\"app\") \n ); ","commentTags":["image"],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1192","displayCommentEventSequenceNumber":1192}],"ev-1217":[{"id":"commentId-10","developerGroupId":"devGroupId-2","timestamp":1612644307919,"commentText":"Next, I add a new style property to the object. The value is another object that specifies a particular style that you might see in a style sheet. I want the h1's foreground color to be green. This will change the color of the text. The attached screenshot shows the new look. You can use css style sheets instead of setting styles manually in this object.","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"style: {color: \"green\"}","startRow":20,"startColumn":43,"endRow":20,"endColumn":66,"selectedTextEventIds":["ev-1193","ev-1194","ev-1195","ev-1196","ev-1197","ev-1198","ev-1199","ev-1200","ev-1201","ev-1202","ev-1203","ev-1204","ev-1205","ev-1206","ev-1207","ev-1208","ev-1209","ev-1210","ev-1211","ev-1212","ev-1213","ev-1214","ev-1215","ev-1216"]}],"imageURLs":["/media/images/pb617-1612644263581-image.png"],"videoURLs":[],"audioURLs":[],"linesAbove":"1","linesBelow":"2","currentFilePath":"/index.html","viewableBlogText":" ReactDOM.render( \n React.createElement(\"h1\", {style: {color: \"green\"}, className: \"display-4\"}, \"Hello World!!!\"), \n document.getElementById(\"app\") \n ); ","commentTags":["image"],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1217","displayCommentEventSequenceNumber":1217},{"id":"commentId-11","developerGroupId":"devGroupId-2","timestamp":1612644355640,"commentText":"I want to recreate the beginning of the CS Legends page that I have been building throughout this book. Next, I will change what I have to make it look like that page.
","selectedCodeBlocks":[],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"0","currentFilePath":"/index.html","viewableBlogText":"","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1217","displayCommentEventSequenceNumber":1217}],"ev-1385":[{"id":"commentId-12","developerGroupId":"devGroupId-2","timestamp":1612644475554,"commentText":"
In order to do this I'll create an h1 with the text \"Computer Science Legends\" and the bootstrap class display-3.
","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"\"h1\", {className: \"display-3\"}, \"Computer Science Legends\"","startRow":20,"startColumn":36,"endRow":20,"endColumn":94,"selectedTextEventIds":["ev-899","ev-901","ev-902","ev-900","ev-903","ev-904","ev-905","ev-1171","ev-1172","ev-1173","ev-1174","ev-1175","ev-1176","ev-1177","ev-1178","ev-1179","ev-1180","ev-1181","ev-1182","ev-1183","ev-1184","ev-1185","ev-1186","ev-1187","ev-1188","ev-1189","ev-1190","ev-1244","ev-1192","ev-908","ev-909","ev-910","ev-911","ev-1259","ev-1260","ev-1261","ev-1262","ev-1263","ev-1264","ev-1265","ev-1266","ev-1267","ev-1268","ev-1269","ev-1270","ev-1271","ev-1272","ev-1273","ev-1274","ev-1275","ev-1276","ev-1277","ev-1278","ev-1279","ev-1280","ev-1281","ev-1282","ev-912","ev-1283"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"1","linesBelow":"2","currentFilePath":"/index.html","viewableBlogText":" ReactDOM.render( \n React.createElement(\"h1\", {className: \"display-3\"}, \"Computer Science Legends\", React.createElement('p', {className: 'lead'}, 'This is a page to hold information about CS legends.')), \n document.getElementById(\"app\") \n ); ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1385","displayCommentEventSequenceNumber":1385},{"id":"commentId-13","developerGroupId":"devGroupId-2","timestamp":1612644627756,"commentText":"If you recall from the previous examples I also had a paragraph tag with the bootstrap class lead. It turns out that the React.createElement method can take any number of child elements after the element type and attribute objects. 

So, if I want a paragraph to be added I can call createElement again right after the text for the h1. The attached screenshot shows the new page.
","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"React.createElement('p', {className: 'lead'}, 'This is a page to hold information about CS legends.')","startRow":20,"startColumn":96,"endRow":20,"endColumn":197,"selectedTextEventIds":["ev-1285","ev-1286","ev-1287","ev-1288","ev-1289","ev-1290","ev-1291","ev-1292","ev-1293","ev-1294","ev-1295","ev-1296","ev-1297","ev-1298","ev-1299","ev-1300","ev-1301","ev-1302","ev-1303","ev-1304","ev-1305","ev-1306","ev-1307","ev-1308","ev-1309","ev-1310","ev-1311","ev-1312","ev-1313","ev-1314","ev-1315","ev-1316","ev-1317","ev-1318","ev-1319","ev-1320","ev-1321","ev-1322","ev-1323","ev-1324","ev-1325","ev-1326","ev-1327","ev-1328","ev-1329","ev-1330","ev-1331","ev-1332","ev-1333","ev-1334","ev-1335","ev-1336","ev-1337","ev-1338","ev-1339","ev-1340","ev-1341","ev-1342","ev-1343","ev-1344","ev-1345","ev-1346","ev-1347","ev-1348","ev-1349","ev-1350","ev-1351","ev-1352","ev-1353","ev-1354","ev-1355","ev-1356","ev-1357","ev-1358","ev-1359","ev-1360","ev-1361","ev-1362","ev-1363","ev-1364","ev-1365","ev-1366","ev-1367","ev-1368","ev-1369","ev-1370","ev-1371","ev-1372","ev-1373","ev-1374","ev-1375","ev-1376","ev-1377","ev-1378","ev-1379","ev-1380","ev-1381","ev-1382","ev-1383","ev-1384","ev-1385","ev-897"]}],"imageURLs":["/media/images/pb617-1612644533177-image.png"],"videoURLs":[],"audioURLs":[],"linesAbove":"1","linesBelow":"2","currentFilePath":"/index.html","viewableBlogText":" ReactDOM.render( \n React.createElement(\"h1\", {className: \"display-3\"}, \"Computer Science Legends\", React.createElement('p', {className: 'lead'}, 'This is a page to hold information about CS legends.')), \n document.getElementById(\"app\") \n ); ","commentTags":["image"],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1385","displayCommentEventSequenceNumber":1385},{"id":"commentId-14","developerGroupId":"devGroupId-2","timestamp":1612644909814,"commentText":"I can use a comma separated list of child elements and add as many as I'd like. However, you can probably already tell that this will be a pain and lead to some pretty ugly code. There is a better way.

React allows you to specify complex hierarchical tag relationships with JSX. This is an XML-like syntax for specifying how elements relate to each other. In addition, I'll offload the creation of the component to a function in the next step.
","selectedCodeBlocks":[],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"0","currentFilePath":"/index.html","viewableBlogText":"","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-1385","displayCommentEventSequenceNumber":1385}],"ev-2004":[{"id":"commentId-15","developerGroupId":"devGroupId-2","timestamp":1612644976408,"commentText":"I will create a custom component that displays the heading for my CS Legends page. In React, one way to create a component is to define a function that returns some JSX (I will use classes to create components in later playbacks). Here I have created a new file, CustomHeader.js, to hold this function called CustomHeader.","selectedCodeBlocks":[{"fileId":"fileId-1","selectedText":"unction CustomHeader()","startRow":0,"startColumn":1,"endRow":0,"endColumn":23,"selectedTextEventIds":["ev-1388","ev-1389","ev-1390","ev-1391","ev-1392","ev-1393","ev-1394","ev-1395","ev-1396","ev-1397","ev-1398","ev-1399","ev-1400","ev-1401","ev-1402","ev-1403","ev-1404","ev-1405","ev-1406","ev-1407","ev-1408","ev-1409","ev-1410"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"7","currentFilePath":"/CustomHeader.js","viewableBlogText":"function CustomHeader() { \n return ( \n
\n

Computer Science Legends

\n

This is a page to hold information about CS legends.

\n
\n ); \n}","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2004","displayCommentEventSequenceNumber":2004},{"id":"commentId-16","developerGroupId":"devGroupId-2","timestamp":1612645049040,"commentText":"The function returns some JSX. JSX was created by the React team to simplify composing components together. This JSX looks a lot like plain old html. I have created a div with an h1 and a paragraph tag. Remember, though this is inside of a javascript function. All component functions must returns some JSX.","selectedCodeBlocks":[{"fileId":"fileId-1","selectedText":"
\n

Computer Science Legends

\n

This is a page to hold information about CS legends.

\n
","startRow":2,"startColumn":8,"endRow":5,"endColumn":14,"selectedTextEventIds":["ev-1449","ev-1450","ev-1451","ev-1452","ev-1453","ev-1460","ev-1461","ev-1462","ev-1463","ev-1464","ev-1465","ev-1466","ev-1467","ev-1468","ev-1469","ev-1470","ev-1471","ev-1472","ev-1473","ev-1484","ev-1485","ev-1486","ev-1487","ev-1488","ev-1489","ev-1490","ev-1491","ev-1492","ev-1493","ev-1494","ev-1495","ev-1496","ev-1497","ev-1498","ev-1500","ev-1501","ev-1502","ev-1503","ev-1504","ev-1505","ev-1506","ev-1507","ev-1508","ev-1499","ev-1509","ev-1515","ev-1516","ev-1517","ev-1518","ev-1519","ev-1520","ev-1521","ev-1522","ev-1523","ev-1524","ev-1525","ev-1526","ev-1527","ev-1528","ev-1529","ev-1530","ev-1531","ev-1532","ev-1533","ev-1534","ev-1535","ev-1536","ev-1537","ev-1538","ev-1510","ev-1511","ev-1512","ev-1513","ev-1514","ev-1539","ev-1540","ev-1541","ev-1542","ev-1543","ev-1544","ev-1545","ev-1546","ev-1547","ev-1548","ev-1549","ev-1550","ev-1551","ev-1552","ev-1553","ev-1554","ev-1555","ev-1556","ev-1557","ev-1558","ev-1559","ev-1560","ev-1561","ev-1562","ev-1563","ev-1564","ev-1565","ev-1566","ev-1568","ev-1569","ev-1570","ev-1571","ev-1567","ev-1572","ev-1577","ev-1578","ev-1579","ev-1580","ev-1581","ev-1582","ev-1583","ev-1584","ev-1585","ev-1586","ev-1587","ev-1588","ev-1589","ev-1590","ev-1591","ev-1592","ev-1593","ev-1594","ev-1595","ev-1596","ev-1597","ev-1598","ev-1599","ev-1600","ev-1601","ev-1602","ev-1603","ev-1604","ev-1605","ev-1606","ev-1607","ev-1608","ev-1609","ev-1610","ev-1611","ev-1612","ev-1613","ev-1614","ev-1615","ev-1616","ev-1617","ev-1618","ev-1619","ev-1620","ev-1621","ev-1622","ev-1623","ev-1624","ev-1625","ev-1626","ev-1627","ev-1628","ev-1573","ev-1574","ev-1575","ev-1576","ev-1474","ev-1475","ev-1476","ev-1477","ev-1478","ev-1479","ev-1480","ev-1481","ev-1482","ev-1483","ev-1454","ev-1455","ev-1456","ev-1457","ev-1458","ev-1459","ev-1443"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"2","linesBelow":"2","currentFilePath":"/CustomHeader.js","viewableBlogText":"function CustomHeader() { \n return ( \n
\n

Computer Science Legends

\n

This is a page to hold information about CS legends.

\n
\n ); \n}","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2004","displayCommentEventSequenceNumber":2004},{"id":"commentId-17","developerGroupId":"devGroupId-2","timestamp":1612645090741,"commentText":"I am returning this JSX from my component function. The way JSX works is that you can only return a single containing element but it can have as many children elements as needed. Here I am returning the div which contains the other elements. The parentheses after the return are to make the code more readable.","selectedCodeBlocks":[{"fileId":"fileId-1","selectedText":"return (","startRow":1,"startColumn":4,"endRow":1,"endColumn":12,"selectedTextEventIds":["ev-1421","ev-1422","ev-1423","ev-1424","ev-1425","ev-1426","ev-1427","ev-1428","ev-1433"]},{"fileId":"fileId-1","selectedText":");","startRow":6,"startColumn":4,"endRow":6,"endColumn":6,"selectedTextEventIds":["ev-1431","ev-1432","ev-1415"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"1","linesBelow":"1","currentFilePath":"/CustomHeader.js","viewableBlogText":"function CustomHeader() { \n return ( \n
\n

Computer Science Legends

\n

This is a page to hold information about CS legends.

\n
\n ); \n}","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2004","displayCommentEventSequenceNumber":2004},{"id":"commentId-18","developerGroupId":"devGroupId-2","timestamp":1612645164654,"commentText":"JSX is not something that browsers understand. There is a tool called Babel which will convert all JSX code into calls to React.createElement. In order to use Babel I can retrieve a copy from the same content distribution network where I am getting the React code. ","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":" ","startRow":17,"startColumn":8,"endRow":17,"endColumn":82,"selectedTextEventIds":["ev-1637","ev-1638","ev-1639","ev-1640","ev-1641","ev-1642","ev-1643","ev-1644","ev-1645","ev-1646","ev-1647","ev-1648","ev-1649","ev-1650","ev-1651","ev-1652","ev-1653","ev-1654","ev-1655","ev-1656","ev-1657","ev-1658","ev-1659","ev-1660","ev-1661","ev-1662","ev-1663","ev-1664","ev-1665","ev-1666","ev-1667","ev-1668","ev-1669","ev-1670","ev-1671","ev-1672","ev-1673","ev-1674","ev-1675","ev-1676","ev-1677","ev-1678","ev-1679","ev-1680","ev-1681","ev-1682","ev-1683","ev-1684","ev-1685","ev-1686","ev-1687","ev-1688","ev-1689","ev-1690","ev-1691","ev-1692","ev-1693","ev-1694","ev-1695","ev-1696","ev-1697","ev-1698","ev-1699","ev-1700","ev-1701","ev-1702","ev-1703","ev-1704","ev-1705","ev-1706","ev-1707","ev-1708","ev-1709","ev-1710","ev-1711"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"2","linesBelow":"0","currentFilePath":"/index.html","viewableBlogText":" \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2004","displayCommentEventSequenceNumber":2004},{"id":"commentId-19","developerGroupId":"devGroupId-2","timestamp":1612645270390,"commentText":"Next, I have to tell Babel which code to compile. I can do this by adding a new script tag with the type \"text/babel\". Now, the file CustomHeader.js will be retrieved from the file system and sent through Babel to convert that JSX code into calls to createElement.

createElement is difficult to use manually if there are a lot of nested components inside each other. The Babel compiler converts all of that friendly JSX into calls to createElement. It writes all of that messy code so I don't have to.
","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"","startRow":19,"startColumn":8,"endRow":19,"endColumn":65,"selectedTextEventIds":["ev-1730","ev-1731","ev-1732","ev-1733","ev-1734","ev-1735","ev-1736","ev-1737","ev-1738","ev-1739","ev-1740","ev-1741","ev-1742","ev-1743","ev-1744","ev-1745","ev-1746","ev-1747","ev-1748","ev-1749","ev-1750","ev-1751","ev-1752","ev-1753","ev-1754","ev-1755","ev-1756","ev-1757","ev-1758","ev-1759","ev-1760","ev-1761","ev-1762","ev-1763","ev-1764","ev-1765","ev-1766","ev-1767","ev-1768","ev-1769","ev-1770","ev-1771","ev-1772","ev-1773","ev-1774","ev-1775","ev-1776","ev-1777","ev-1778","ev-1779","ev-1780","ev-1781","ev-1782","ev-1783","ev-1784","ev-1785","ev-1786","ev-1787"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"4","linesBelow":"7","currentFilePath":"/index.html","viewableBlogText":" \n \n \n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2004","displayCommentEventSequenceNumber":2004},{"id":"commentId-20","developerGroupId":"devGroupId-2","timestamp":1612645361399,"commentText":"I will do the same with my script in index.html because I am making a change to use JSX in the call to render as well.","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"script type=\"text/babel\"","startRow":21,"startColumn":9,"endRow":21,"endColumn":33,"selectedTextEventIds":["ev-767","ev-768","ev-769","ev-770","ev-771","ev-772","ev-1789","ev-1790","ev-1791","ev-1792","ev-1793","ev-1794","ev-1795","ev-1796","ev-1797","ev-1798","ev-1799","ev-1800","ev-1801","ev-1802","ev-1803","ev-1804","ev-1805","ev-1806","ev-773"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"13","linesBelow":"6","currentFilePath":"/index.html","viewableBlogText":" \n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2004","displayCommentEventSequenceNumber":2004},{"id":"commentId-21","developerGroupId":"devGroupId-2","timestamp":1612645540050,"commentText":"Now that I changed the script's type from the default of javascript to Babel I can use JSX syntax to create my custom component. When Babel sees a tag that starts with an uppercase letter it will assume I want to use a custom component (JSX elements that start with a lowercase letter are assumed to be plain old html elements). It will look for a function with the name CustomHeader, call it, and return the element created from JSX.

If you run the program now you will see a nearly identical page as before. The only problem is that this is not really a custom header. It can only be used in my CS Legend app. I'll make the component more reusable next.
","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"","startRow":23,"startColumn":16,"endRow":23,"endColumn":32,"selectedTextEventIds":["ev-1989","ev-1990","ev-1991","ev-1992","ev-1993","ev-1994","ev-1995","ev-1996","ev-1997","ev-1998","ev-1999","ev-2000","ev-2001","ev-2002","ev-2003","ev-2004","ev-928"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"15","linesBelow":"4","currentFilePath":"/index.html","viewableBlogText":" \n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2004","displayCommentEventSequenceNumber":2004}],"ev-2210":[{"id":"commentId-22","developerGroupId":"devGroupId-2","timestamp":1612645612690,"commentText":"A React component function can have 'props' or properties. These are immutable values sent in to the function and used to create the user interface returned from the function. For this component, every custom header needs a title and subtitle.","selectedCodeBlocks":[{"fileId":"fileId-1","selectedText":"{title, subtitle}","startRow":0,"startColumn":22,"endRow":0,"endColumn":39,"selectedTextEventIds":["ev-2101","ev-2102","ev-2103","ev-2104","ev-2105","ev-2106","ev-2107","ev-2108","ev-2109","ev-2110","ev-2111","ev-2112","ev-2113","ev-2114","ev-2115","ev-2116","ev-2117","ev-1409"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"7","currentFilePath":"/CustomHeader.js","viewableBlogText":"function CustomHeader({title, subtitle}) { \n return ( \n
\n

{title}

\n

{subtitle}

\n
\n ); \n}","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2210","displayCommentEventSequenceNumber":2210},{"id":"commentId-23","developerGroupId":"devGroupId-2","timestamp":1612645703716,"commentText":"The function's parameters are called title and subtitle. I can go from JSX mode back to plain javascript by using a set of curly braces inside the JSX. Babel will use the values of the parameters when creating the elements.

The highlighted code says to take the values of title and subtitle and place them in the h1 and p tags respectively. 

Now this component can be reused in different places or even in React different apps.
","selectedCodeBlocks":[{"fileId":"fileId-1","selectedText":"title","startRow":3,"startColumn":39,"endRow":3,"endColumn":44,"selectedTextEventIds":["ev-2143","ev-2144","ev-2145","ev-2146","ev-2147","ev-2148"]},{"fileId":"fileId-1","selectedText":"subtitle","startRow":4,"startColumn":33,"endRow":4,"endColumn":41,"selectedTextEventIds":["ev-2202","ev-2203","ev-2204","ev-2205","ev-2206","ev-2207","ev-2208","ev-2209","ev-2210"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"3","linesBelow":"3","currentFilePath":"/CustomHeader.js","viewableBlogText":"function CustomHeader({title, subtitle}) { \n return ( \n
\n

{title}

\n

{subtitle}

\n
\n ); \n}","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2210","displayCommentEventSequenceNumber":2210},{"id":"commentId-24","developerGroupId":"devGroupId-2","timestamp":1612645807806,"commentText":"The props are defined in the JSX like this. Babel will make a new object that looks like this:

{
    title: \"Computer Science Legends\",
    subtitle: \"This is a page to hold information about CS legends.\"
}

and it will pass it into the function to be used.
","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"title=\"Computer Science Legends\" subtitle=\"This is a page to hold information about CS legends.\"","startRow":23,"startColumn":30,"endRow":23,"endColumn":126,"selectedTextEventIds":["ev-2005","ev-2006","ev-2007","ev-2008","ev-2009","ev-2010","ev-2011","ev-2012","ev-2013","ev-2014","ev-2015","ev-2016","ev-2017","ev-2018","ev-2019","ev-2020","ev-2021","ev-2022","ev-2023","ev-2024","ev-2025","ev-2026","ev-2027","ev-2028","ev-2029","ev-2030","ev-2031","ev-2032","ev-2033","ev-2034","ev-2035","ev-2036","ev-2037","ev-2038","ev-2039","ev-2040","ev-2041","ev-2042","ev-2043","ev-2044","ev-2045","ev-2046","ev-2047","ev-2048","ev-2049","ev-2050","ev-2051","ev-2052","ev-2053","ev-2054","ev-2055","ev-2056","ev-2057","ev-2058","ev-2059","ev-2060","ev-2061","ev-2062","ev-2063","ev-2064","ev-2065","ev-2066","ev-2067","ev-2068","ev-2069","ev-2070","ev-2071","ev-2072","ev-2073","ev-2074","ev-2075","ev-2076","ev-2077","ev-2078","ev-2079","ev-2080","ev-2081","ev-2082","ev-2083","ev-2084","ev-2085","ev-2086","ev-2087","ev-2088","ev-2089","ev-2090","ev-2091","ev-2092","ev-2093","ev-2094","ev-2095","ev-2096","ev-2097","ev-2098","ev-2099","ev-2100","ev-2003"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"1","linesBelow":"2","currentFilePath":"/index.html","viewableBlogText":" ReactDOM.render( \n , \n document.getElementById(\"app\") \n ); ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2210","displayCommentEventSequenceNumber":2210},{"id":"commentId-25","developerGroupId":"devGroupId-2","timestamp":1612646018939,"commentText":"Let me explain this set of curly braces in the parameter list. This is an example of 'object destructuring' in javascript. This says to create two parameters for the function called title and subtitle. These parameters will get their values from the props object passed in to the function.

Recall that this object will be created by Babel and sent in to the CustomHeader function:

{
    title: \"Computer Science Legends\",
    subtitle: \"This is a page to hold information about CS legends.\"
}


With destructuring the parameters are matched by name to properties in the passed in object.

In other words, since the passed in object has a property called title the parameter with the same name will get the value \"Computer Science Legends\". The same is true with the subtitle parameter. The parameter list is filled in from values from the object.
","selectedCodeBlocks":[{"fileId":"fileId-1","selectedText":"{","startRow":0,"startColumn":22,"endRow":0,"endColumn":23,"selectedTextEventIds":["ev-2101","ev-2102"]},{"fileId":"fileId-1","selectedText":"}","startRow":0,"startColumn":38,"endRow":0,"endColumn":39,"selectedTextEventIds":["ev-2117","ev-1409"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"7","currentFilePath":"/CustomHeader.js","viewableBlogText":"function CustomHeader({title, subtitle}) { \n return ( \n
\n

{title}

\n

{subtitle}

\n
\n ); \n}","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2210","displayCommentEventSequenceNumber":2210},{"id":"commentId-26","developerGroupId":"devGroupId-2","timestamp":1612646126102,"commentText":"
The object destructuring is optional. It is perfectly ok to just accept the props object as is. The only difference is that you have to use dot notation to retrieve the properties:
 
function CustomHeader(props) {
    return (
        <div>
            <h1 className=\"display-3\">{props.title}</h1>
            <p className=\"lead\">{props.subtitle}</p>
        </div>
    );
}

In the original call to createElement() the second argument was the props object.

The two approaches are equivalent. Having said that, most React developers choose to destructure their props.
","selectedCodeBlocks":[{"fileId":"fileId-1","selectedText":"{title, subtitle}","startRow":0,"startColumn":22,"endRow":0,"endColumn":39,"selectedTextEventIds":["ev-2101","ev-2102","ev-2103","ev-2104","ev-2105","ev-2106","ev-2107","ev-2108","ev-2109","ev-2110","ev-2111","ev-2112","ev-2113","ev-2114","ev-2115","ev-2116","ev-2117","ev-1409"]},{"fileId":"fileId-1","selectedText":"{title}","startRow":3,"startColumn":38,"endRow":3,"endColumn":45,"selectedTextEventIds":["ev-2142","ev-2143","ev-2144","ev-2145","ev-2146","ev-2147","ev-2148","ev-1510"]},{"fileId":"fileId-1","selectedText":"{subtitle}","startRow":4,"startColumn":32,"endRow":4,"endColumn":42,"selectedTextEventIds":["ev-2201","ev-2202","ev-2203","ev-2204","ev-2205","ev-2206","ev-2207","ev-2208","ev-2209","ev-2210","ev-1573"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"3","currentFilePath":"/CustomHeader.js","viewableBlogText":"function CustomHeader({title, subtitle}) { \n return ( \n
\n

{title}

\n

{subtitle}

\n
\n ); \n}","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2210","displayCommentEventSequenceNumber":2210}],"ev-2667":[{"id":"commentId-27","developerGroupId":"devGroupId-2","timestamp":1612646283239,"commentText":"To prove that this is a reusable component I'll add another custom header on the same page. First I'll create another div with a different id, app2, underneath the original in index.html.","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"
\n \n
","startRow":13,"startColumn":12,"endRow":15,"endColumn":18,"selectedTextEventIds":["ev-2237","ev-2238","ev-2239","ev-2240","ev-2241","ev-2242","ev-2243","ev-2244","ev-2245","ev-2246","ev-2247","ev-2248","ev-2249","ev-2250","ev-2251","ev-2252","ev-2253","ev-2447","ev-2448","ev-2449","ev-2450","ev-2451","ev-2452","ev-2453","ev-2454","ev-2455","ev-2456","ev-2457","ev-2458","ev-2459","ev-2460","ev-2461","ev-2462","ev-2270","ev-2271","ev-2272","ev-2273","ev-2274","ev-2275","ev-2276","ev-2277","ev-2278","ev-2279","ev-2280","ev-2281","ev-2282","ev-2283","ev-2284","ev-2285","ev-2286","ev-2287","ev-2288","ev-2289","ev-2290","ev-2291","ev-2292","ev-2293","ev-2294","ev-2295","ev-2296","ev-2297","ev-2298","ev-2299","ev-2300","ev-2301","ev-2302","ev-2303","ev-2304","ev-2305","ev-2306","ev-2307","ev-2308","ev-2309","ev-2310","ev-2311","ev-2312","ev-2313","ev-2314","ev-2315","ev-2316","ev-2415","ev-2416","ev-2417","ev-2418","ev-2419","ev-2420","ev-2421","ev-2422","ev-2423","ev-2424","ev-2425","ev-2426","ev-2329","ev-2330","ev-2331","ev-2332","ev-2333","ev-2334","ev-2213"]}],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"5","linesBelow":"20","currentFilePath":"/index.html","viewableBlogText":" \n
\n
\n \n
\n
\n \n
\n
\n \n \n \n \n \n \n \n \n ","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2667","displayCommentEventSequenceNumber":2667},{"id":"commentId-28","developerGroupId":"devGroupId-2","timestamp":1612646341725,"commentText":"Then I'll create another instance of a custom header but I will pass in different values for the props. The attached screenshot shows the output.","selectedCodeBlocks":[{"fileId":"fileId-0","selectedText":"ReactDOM.render( \n , \n document.getElementById('app2') \n );","startRow":30,"startColumn":12,"endRow":33,"endColumn":14,"selectedTextEventIds":["ev-2489","ev-2490","ev-2491","ev-2492","ev-2493","ev-2494","ev-2495","ev-2496","ev-2497","ev-2498","ev-2499","ev-2500","ev-2501","ev-2502","ev-2503","ev-2504","ev-2505","ev-2506","ev-2507","ev-2508","ev-2509","ev-2510","ev-2511","ev-2512","ev-2513","ev-2514","ev-2515","ev-2516","ev-2517","ev-2518","ev-2519","ev-2520","ev-2521","ev-2522","ev-2523","ev-2524","ev-2525","ev-2526","ev-2527","ev-2528","ev-2529","ev-2530","ev-2531","ev-2532","ev-2533","ev-2534","ev-2535","ev-2536","ev-2537","ev-2538","ev-2539","ev-2540","ev-2541","ev-2542","ev-2543","ev-2544","ev-2545","ev-2546","ev-2547","ev-2548","ev-2549","ev-2550","ev-2551","ev-2552","ev-2553","ev-2554","ev-2555","ev-2556","ev-2557","ev-2558","ev-2559","ev-2560","ev-2561","ev-2562","ev-2563","ev-2564","ev-2565","ev-2566","ev-2567","ev-2568","ev-2569","ev-2570","ev-2571","ev-2572","ev-2573","ev-2574","ev-2575","ev-2576","ev-2577","ev-2578","ev-2579","ev-2580","ev-2581","ev-2582","ev-2583","ev-2584","ev-2585","ev-2586","ev-2587","ev-2588","ev-2589","ev-2590","ev-2591","ev-2592","ev-2593","ev-2594","ev-2595","ev-2596","ev-2597","ev-2598","ev-2599","ev-2600","ev-2601","ev-2602","ev-2603","ev-2604","ev-2605","ev-2606","ev-2607","ev-2608","ev-2609","ev-2610","ev-2611","ev-2612","ev-2613","ev-2614","ev-2615","ev-2616","ev-2617","ev-2618","ev-2619","ev-2620","ev-2621","ev-2622","ev-2623","ev-2624","ev-2625","ev-2626","ev-2627","ev-2628","ev-2629","ev-2630","ev-2631","ev-2632","ev-2633","ev-2634","ev-2635","ev-2636","ev-2637","ev-2638","ev-2639","ev-2640","ev-2641","ev-2642","ev-2643","ev-2644","ev-2645","ev-2646","ev-2647","ev-2648","ev-2649","ev-2650","ev-2651","ev-2652","ev-2653","ev-2465"]}],"imageURLs":["/media/images/pb617-1612646335460-image.png"],"videoURLs":[],"audioURLs":[],"linesAbove":"6","linesBelow":"1","currentFilePath":"/index.html","viewableBlogText":" ","commentTags":["image"],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2667","displayCommentEventSequenceNumber":2667},{"id":"commentId-29","developerGroupId":"devGroupId-2","timestamp":1612646407879,"commentText":"In this playback I have showed how to:
- use ReactDOM.render to create a component in a web page
- create an html element using React.createElement
- use JSX to simplify element creation including how to create custom elements
- use props to send data into a component function

Next, I'll show how to create more complex components to recreate the entire CS Legends site.
","selectedCodeBlocks":[],"imageURLs":[],"videoURLs":[],"audioURLs":[],"linesAbove":"0","linesBelow":"0","currentFilePath":"/index.html","viewableBlogText":"","commentTags":[],"questionCommentData":null,"commentTitle":"","displayCommentEventId":"ev-2667","displayCommentEventSequenceNumber":2667}]}; playbackData.numEvents = 2668; playbackData.isEditable = false; playbackData.developers = {"devId-0":{"id":"devId-0","userName":"Storyteller System","email":"system@ourcodestories.com","avatarURL":"https://www.gravatar.com/avatar/5fcc05d044610e96c28c9bb4b7278935"},"devId-1":{"id":"devId-1","userName":"Anonymous Developer","email":"anon@ourcodestories.com","avatarURL":"https://www.gravatar.com/avatar/265e214b9c99f4d4f703c6feb9d8652f"},"devId-2":{"id":"devId-2","userName":"Mark Mahoney","email":"mmahoney@carthage.edu","avatarURL":"https://www.gravatar.com/avatar/8f406804248006f79761e9ebc39d414c"}}; playbackData.developerGroups = {"devGroupId-0":{"id":"devGroupId-0","memberIds":["devId-0"]},"devGroupId-1":{"id":"devGroupId-1","memberIds":["devId-1"]},"devGroupId-2":{"id":"devGroupId-2","memberIds":["devId-2"]}}; playbackData.playbackTitle = 'Basic React'; playbackData.branchId = 'umt0k'; playbackData.estimatedReadTime = 19; }