You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
15 KiB

import { addBanner, addArticle, addTitle, addHeader, addParagraph, addClassParagraph, addSubHeader, addOrderedList, addUnorderedList, addBlockquote, addInset, addInsetList, addInsetCodeListing, addInsetBulletList, addImageWithCaption, addButtonGroup, addSidebar, addSyntax, menu, global_menu } from '/scripts/import.js';
import { local_menu } from '/scripts/webdev.js';
const heading = document.querySelector(".heading");
const global = document.querySelector(".global_menu");
const local = document.querySelector(".local_menu");
const sidebar = document.querySelector(".sidebar");
const main = document.querySelector(".main_content");
heading.append(addTitle("Learning ReactJS"));
heading.append(addParagraph("Eve Porcello - LinkedIn Learning"));
heading.append(addParagraph("Chapter 2 - React Elements"));
main.append(addSubHeader("Creating a React Element"));
main.append(addParagraph("We will now do some more coding on our hello-react app. Before I do that, I have two shells open to my Raspberry Pi and I am using one of them to run the app so I want to make sure that is running by typing the command"));
main.append(addSyntax("npm start"));
main.append(addParagraph("To be certain, I have checked that in a browser and I can see my edited version of the app as shown in figure 11. In the other shell, I will do the actual editing. "));
main.append(addParagraph("We will start by editing the index.js file which is shown, for reference, in figure 15. "));
main.append(addImageWithCaption("./images/figure15.png", "Figure 15 - the index.js file before we start to edit it"));
main.append(addParagraph("We will remove the comment between lines 14 and 16 and also the statement on line 17. We are also going to remove the App component from line 9 (its inside the React.StrictMode tag so we will also delete lines 8 and 10 and we can remove the import statements for both App and reportWebVitals. "));
main.append(addParagraph("This leaves ReactDom.render with a single argument. It actually takes two, the element that we want to create (which was App) and the location in which it should be rendered (in the 'root' div). "));
main.append(addParagraph("We want to create an element which we will do with the React.createElement function which takes three arguments."));
main.append(addInsetBulletList(["The name of the tag we want to create.", "Any properties we want the element to have.", "Any children (this could be another tag or just some text to display."]));
main.append(addParagraph("The statement would therefore look something like this"));
main.append(addSyntax("[React.createElement(\"h1\", null, \"Hello!\"),"));
main.append(addParagraph("A couple of points about this. Firstly, the name of the tag, if not the format, is immediately recognisable as an HTML tag so it is clear that we are inserting a header. Secondly, we are not specifying any particular properties, so the second argument is null."));
main.append(addParagraph("The revised version of index.js is"));
main.append(addImageWithCaption("./images/figure16.png", "Figure 16 - the revised version of index.js file with our own element replacing App and the other changes made as described above"));
main.append(addParagraph("We can now go back to the browser and refresh the page and we should see the new HTML tag as shown in figure 17."));
main.append(addImageWithCaption("./images/image8.png", "Figure 17 - our revised app showing the new tag we created with the React.createElement function in figure 17"));
main.append(addParagraph("We can right-click on our header in the browser and select Inspect Element and the results are shown in figure 18. "));
main.append(addImageWithCaption("./images/image9.png", "Figure 18 - using the developer tools to inspect the header that we can see in the page shown in figure 17"));
main.append(addParagraph("We can see that our text is wrapped up in an <h1> tag and this is inside a <div> called root. Recall that the second element in our ReactDOM.render function is "));
main.append(addSyntax("[.getElementById('root') "));
main.append(addParagraph("which we had described as 'the location in which it should be rendered'. We are making a function call to getElementById with 'root' as an argument and so this is returning the 'root' div and so this is the div we place our element inside. "));
main.append(addParagraph("If we look inside the public folder in our app, there is a file called index.html. This is shown in figure 19. "));
main.append(addImageWithCaption("./images/figure19.png", "Figure 19 - the contents of the index.html file inside the public folder"));
main.append(addParagraph("On line 31, we have the 'root' div which is empty, so when we run the application, this is where the element we created in index.js is being injected. "));
main.append(addParagraph("We could create any type of HTML tag in this way so this could have been a h2 tag or a p tag."));
main.append(addParagraph("Rather than null as the second argument for React.createElement, we could pass in an object that would apply some style to the new element. The general syntax for this is"));
main.append(addSyntax("[{ style: { attribute: \"value\" } }"));
main.append(addParagraph("For example, if we wanted to change the text colour to blue, this would be"));
main.append(addSyntax("[{ style: { color: \"blue\" } }"));
main.append(addParagraph("So these React elements are, in essence, the building blocks of React applications. Next, we will look at putting these together to create more complex user interfaces."));
main.append(addSubHeader("Rendering Multiple React Elements"));
main.append(addParagraph("We managed to render a React element in the DOM, but we can also render multiple elements by changing the third argument so that rather than this being simply a piece of text, it is a nested call to React.createElement. "));
main.append(addParagraph("Previously, we had called the function with"));
main.append(addSyntax("[React.createElement(\"h1\", null, \"Hello!\"),"));
main.append(addParagraph("Essentially, what we now want to do is to take this whole call and use it as the third argument, giving us"));
main.append(addSyntax("[React.createElement(\"div\", null, React.createElement(\"h1\", null, \"Hello!\")),"));
main.append(addParagraph("Note that I have also changed the first argument from \"h1\" to \"div\", otherwise we would be creating a <h1> element inside a <h1> element, which doesn't make a lot of sense. By changing it, we are creating a <div> element with our <h1> element inside it."));
main.append(addParagraph("We won't see any difference if we refresh the page, but if we inspect the element, we will certainly see a difference there. We can see the new element in figure 20."));
main.append(addImageWithCaption("./images/image10.png", "Figure 20 - using the developer tools to inspect the header again, this time with the <h1> element created inside a <div> element"));
main.append(addParagraph("This type of technique may be fine for a very simple app, but it can quickly become unwieldy as complexity of the app increases. But there is syntax we can use to make this process a little simpler and make it easier to build user interfaces and we will look at that next."));
main.append(addSubHeader("Introducing JSX"));
main.append(addParagraph("We are going to look at rendering a more complex element, an unordered list. If we wanted to do this with a React.createElement call, it would look like this"));
main.append(addImageWithCaption("./images/figure21.png", "Figure 21 - using React.createElement to generate an unordered list in HTML"));
main.append(addParagraph("We can also do this JSX (JavaScript as XML) which allows us to write tags directly in the JavaScript. This syntax is shown in figure 22."));
main.append(addImageWithCaption("./images/figure22.png", "Figure 22 - using JSX to generate the same unordered list as the one we saw in figure 21"));
main.append(addParagraph("This looks like we are rendering tags automatically in the browser, but that is not the case. What is happening here is that create-react-app is using a tool, in the background, called Babel. Babel allows you to write code that might not work in a browser, either because it is new syntax that is not yet supported or just because (as is the case here, with JSX) it is not supported at all."));
main.append(addParagraph("To understand what is happening here, we can go to the Babel website at <a href=\"https://babeljs.io/\">https://babeljs.io/</a>. From here, we want to click on the Try It Out link at the top of the screen and we can then paste our code in the left-hand pane. The results from this when the course lecturer did this are shown in figure 23."));
main.append(addImageWithCaption("./images/image11.png", "Figure 23 - the results pasting our code into the code box on the Babel website (babeljs.io)"));
main.append(addParagraph("When I tried this myself, I got an error rather than the expected results. The results in figure 23 show that the code which creates an unordered list is being translated into React.createElement calls. These are identical (apart from the style argument) to the calls in figure 17."));
main.append(addParagraph("So, we can say that we are using JSX to write our code that cannot be rendered in a browser, but Babel is translating this to the React.createElement calls that can be rendered in a browser."));
main.append(addParagraph("For reference, the error I am seeing in Babel is shown in figure 24."));
main.append(addImageWithCaption("./images/figure24.png", "Figure 24 - the error in babeljs.io"));
main.append(addParagraph("I'm not going to worry about the error just now, but I will try the website again later. For now, just be aware that Babel is quite closely integrated with React and this allows us to write code using the JSX syntax that is both more readable and easier to write."));
main.append(addSubHeader("Understanding JSX Features"));
main.append(addParagraph("As we saw, JSX syntax is pretty similar to HTML, but there are differences, including the fact that JSX is dynamic. An example of this is shown in figure 25."));
main.append(addImageWithCaption("./images/figure25.png", "Figure 25 - an example of the dynamic syntax possible with JSX using a simple variable"));
main.append(addParagraph("In this example, we have created a variable called city which we have set to a value of \"Madrid\"."));
main.append(addParagraph("In our call to ReactDOM.render function, we have replaced our unordered list with a h1 tag. There is some text in this tag and we have also used our variable (the name of the city) so that it also appears inside the h1 tag."));
main.append(addParagraph("We can also create an object rather than a simple variable, and the syntax here will look quite familiar if you have programmed before in an object-oriented language such as Java."));
main.append(addParagraph("The code for this is shown in figure 26."));
main.append(addImageWithCaption("./images/figure26", "Figure 26 - an example of the dynamic syntax possible with JSX using an object"));
main.append(addParagraph("The differences here are that rather than simply assign a value to city, we have essentially assigned an object to it which has two data members. In this case, they are name with a value of \"Madrid\" and country with a value of \"Spain\"."));
main.append(addParagraph("In the h1 tag, we have used typical object-oriented syntax to dereference the name of the city, so the result is the same as we get with the code in figure 25. Note that we are not making use of the other data member in the object at this point. Also, take note of the fact that although this is recognisably an object, we did not create this in the same way as we would in, for instance, Java. I would guess that is just the React way of doing things, but I guess this will be covered in more detail later. For now, it should be sufficient to note that we seem to be able to create an object quite easily without creating a class first so it is questionable whether this is an object in the usual sense."));
main.append(addParagraph("We can make our h1 tag a little more complex in order to use both data members so the tag might look something like this"));
main.append(addSyntax("[&#60;h1&#62;{city.name} is in {city.country}&#60;/h1&#62;,"));
main.append(addParagraph("The output from this is shown in figure 27."));
main.append(addImageWithCaption("./images/image12.png", "Figure 27 - the output we see using both data elements from out object in a &#60;h1&#62; tag"));
main.append(addParagraph("With JSX, we can also add attributes directly to our tags. To do that, we want to open the index.html file and add the following lines inside the head."));
main.append(addInsetCodeListing(["&lt;style&gt;", " #heading {", " color: red;", " }", "&lt;/style&gt;"]));
main.append(addParagraph("This is creating a style using an id of #heading."));
main.append(addParagraph("Now, if we go back to the index.js file in the src folder, we can give our &#60;h1&#62; tag an id attribute of heading so that it looks like this"));
main.append(addSyntax("[&#60;h1 id='heading'&#62;{city.name} is in {city.country}!&#60;/h1&#62;,"));
main.append(addParagraph("If we refresh the browser, we will see the same result as we saw in figure 27, but this time the text is in red."));
main.append(addParagraph("So, to sum up that, we created the style in the index.html file (in the public folder) for an id (heading). So this style will be applied to any tag in this file that has heading as an id."));
main.append(addParagraph("In the index.js file (in the src folder), we created an h1 tag to which we added an attribute of id (which we gave the value of heading). When this tag is injected into our html page, because it has an id that matches the style we added, it takes the style described there, in other words, it's colour attribute is set to red."));
main.append(addParagraph("I would assume, although I haven't seen this in the course yet, if we have a css file for the styling, we would create a style (as we would for a static html page) in that file. So, to continue with the same example, we would create a style with an id of heading in the css file which is then read into the html file and we would add the heading attribute to the tag we are creating with JSX, just as we did before."));
main.append(addParagraph("We can also do the same thing with a class name. To demonstrate this, let's add a second style to our index.html file so this becomes"));
main.append(addInsetCodeListing(["&lt;style&gt;", " #heading {", " %color: red;", " }", " .cool-text {", " font-family: \"Monaco\";", " }", "&lt;/style&gt;"]));
main.append(addParagraph("In the index.js file, we will also add an attribute for the class name so the &#60;h1&#62; tag now becomes"));
main.append(addSyntax("[&#60;h1 id='heading' className='cool-text'&#62;{city.name} is in {city.country}!&#60;/h1&#62;,"));
main.append(addParagraph("Again, this is just css styling but note that JSX uses className rather than class. If we were adding this tag to a html file, just as plain html file, we would use just class as the attribute name."));
main.append(addImageWithCaption("./images/figure28.png", "Figure 28 - this is our &#60;h1&#62; tag again, this time with modifications to the font and font colour which were added to the index.html file in a style tag"));
3 months ago
addSidebar("webdev");