This commit is contained in:
Micah Godbolt 2019-03-03 17:51:31 -08:00
Родитель 2da055ff1d
Коммит 3acd7d22ec
24 изменённых файлов: 511 добавлений и 425 удалений

Просмотреть файл

@ -16,26 +16,27 @@
<h2>Day 1</h2>
Get set up and learn to build a todo app using HTML, CSS, JavaScript, and React.
</li>
<li class="Tile Tile--numbered">
<a target="_blank" href="./step1-01/" class="Tile-link">
HTML/CSS/JS
</a>
</li>
<li class="Tile Tile--numbered">
<div class="Tile-link">
Todo HTML & CSS
Intro to HTML
<div class="Tile-links">
<a target="_blank" href="./step1-02/demo/">demo</a> | <a target="_blank" href="./step1-02/exercise/">exercise</a> |
<a target="_blank" href="./step1-02/final/">final</a>
<a target="_blank" href="./step1-01/demo/">demo</a> | <a target="_blank" href="./step1-01/exercise/">exercise</a>
</div>
</div>
</li>
<li class="Tile Tile--numbered">
<div class="Tile-link">
Todo JS
Intro to CSS
<div class="Tile-links">
<a target="_blank" href="./step1-03/demo/">demo</a> | <a target="_blank" href="./step1-03/exercise/">exercise</a> |
<a target="_blank" href="./step1-03/final/">final</a>
<a target="_blank" href="./step1-02/demo/">demo</a> | <a target="_blank" href="./step1-02/exercise/">exercise</a>
</div>
</div>
</li>
<li class="Tile Tile--numbered">
<div class="Tile-link">
Intro to JS
<div class="Tile-links">
<a target="_blank" href="./step1-03/demo/">demo</a> | <a target="_blank" href="./step1-03/exercise/">exercise</a>
</div>
</div>
</li>

Просмотреть файл

@ -1,49 +1 @@
# Step 1 Exercise
The power of HTML is its ability to represent complex information in a way that conveys meaning. In this exercise you are going to be creating an HTML page for my favorite recipe.
## The Exercise
1. Create a recipe page to host our recipe (page title, headings, sections, paragraphs, lists etc)
2. Use title, header, main, footer, headings (h1/h2 etc), paragraphs, lists
3. Use ordered and unordered lists appropriately
4. Add the `baked_beans.jpg` iagine included in this folder
5. Add an anchor tag around 'Wisconsin Beer Brats'
## 4th of July Baked Beans
It's great how a single meal can take you back dozens of years. This is one of those recipes that never seems to fail to impress.
I learned this recipe for the cousin of one of my college friends back in Nashville Tenessee. We had an amazing 4th of July feast which included this recipe and some bratworst like these Wisconsin Beer Brats https://www.culinaryhill.com/wisconsin-beer-brats/
Prep Time: 10 minutes
Cook time: 3+ hours
Servings: 12
**Ingredients**
1LB Bacon chopped
3 Cans Bush's Origin Baked Beans
1 Walla Wall Onion chopped
2 ground garlic cloves
3 Tablespoons of mustard
2 Tablespoons of molasses
3 Tablespoons of brown sugar
**Directions**
Cook bacon until it is mostly cooked, then drain most of the grease and put aside
Cook onion in remaining bacon grease
Combine onions and bacon, then add garlic, cook for a few more minutes
Add beans and get up to simmer temperate
Add mustard until your beans are nice and yellow
Add molassas until color darkens again
Add brown sugar until properly sweet
Simmer for a long time, occassionally sturing
**Expert Tipes**
Burning off most of the liquid gives you nice, hearty, sticky beans.
If the beans get too try, you can always add beer!
**Nutritional Information**
Calories: lots
Fat: lots
Fun: lots
Readme is in index.html

Просмотреть файл

@ -1,4 +1,76 @@
<html>
<head></head>
<body></body>
<body>
<div
class="codepen"
data-theme-id="36294"
data-prefill
data-editable="true"
data-height="100%"
data-theme-id="1"
data-default-tab="js,result"
>
<pre data-lang="js">
/*
Step 1 Exercise
The power of HTML is its ability to represent complex information in a way that conveys meaning. In this exercise you are going to be creating an HTML page for my favorite recipe.
## The Exercise
1. Create a recipe page to host our recipe
2. Use title, header, main, footer, headings (h1/h2 etc), paragraphs, lists
3. Use ordered and unordered lists appropriately
4. Add the `baked_beans.jpg` image included in this folder: `https://raw.githubusercontent.com/Microsoft/frontend-bootcamp/master/step1-01/exercise/baked_beans.jpg`
5. Add an anchor tag around 'Wisconsin Beer Brats'
## The Recipe
Title:
4th of July Baked Beans
Description:
It's great how a single meal can take you back dozens of years. This is one of those recipes that never seems to fail to impress.
I learned this recipe from the cousin of one of my college friends back in Nashville Tennessee. We had an amazing 4th of July feast which included this recipe and some bratwurst like these Wisconsin Beer Brats https://www.culinaryhill.com/wisconsin-beer-brats/
Prep Time: 10 minutes
Cook time: 3+ hours
Servings: 12
Ingredients:
1LB Bacon chopped
3 Cans Bush's Original Baked Beans
1 Walla Wall Onion chopped
2 ground garlic cloves
3 Tablespoons of mustard
2 Tablespoons of molasses
3 Tablespoons of brown sugar
Directions:
Cook bacon until it is mostly cooked, then drain most of the grease and put aside
Cook onion in remaining bacon grease
Combine onions and bacon, then add garlic, cook for a few more minutes
Add beans and get up to simmer temperature
Add mustard until your beans are nice and yellow
Add molasses until color darkens again
Add brown sugar until properly sweet
Simmer for a long time, occasionally stirring
Expert Tips:
Burning off most of the liquid gives you nice, hearty, sticky beans.
If the beans get too dry, you can always add beer!
Nutritional Information:
Calories: lots
Fat: lots
Fun: lots
*/
</pre>
<pre data-lang="html">Add Recipe Here</pre>
</div>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
</body>
</html>

Просмотреть файл

@ -48,98 +48,6 @@ Selectors can be a single tag, class, ID, or attribute. It can also be a [combin
Below is a series of selectors and property/value combinations that we'll apply to our CSS demo page.
```css
/* Targeting the entire page */
body {
font: 1.2em sans-serif;
}
/* Targeting an HTML tag */
h1 {
/* Color name */
color: black;
/* 6-digit hex */
background: #ababab;
/* Margin: specified separately for each side */
margin-bottom: 15px;
margin-top: 15px;
/* Shorthand: Padding applies to all sides */
padding: 10px;
/* Border shorthand and 3-digit hex */
border: 1px solid #ddd;
}
/* Overriding inherited styles */
span {
color: #004578;
}
/* Sibling selector */
a ~ a {
/* Changing elements from inline to block */
display: block;
}
/* Targeting a class name */
.tiles {
display: flex;
}
/* Descendant selector */
.tiles img {
width: 100%;
}
/* Direct descendant selector */
.tiles > div {
/* rgb color */
background: rgb(10, 10, 10);
color: white;
flex-basis: 100%;
/* Padding/margin shorthand. Goes clockwise from top.
10px - all
10px 20px - top/bottom left/right
10px 20px 15px - top left/right bottom
*/
padding: 10px 20px 15px;
margin: 10px 20px 10px 0;
border: 1px solid white;
}
/* Qualified selector */
div.important-links {
background: #004578;
}
/* Style inheritance only works for unstyled elements */
a {
color: white;
}
/* Hover pseudo-selector */
a:hover {
color: #ccc;
}
/* Positional pseudo-selector */
.tiles > div:last-child {
/* overrides margin-right but leaves other margins alone */
margin-right: 0;
}
/* ID selector */
#contact-form {
display: flex;
flex-direction: column;
}
/* Attribute selector */
input[type='submit'] {
margin-top: 10px;
}
```
## Next Step

Просмотреть файл

@ -1,29 +0,0 @@
<html>
<head>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<div>
<h1>This is my <span>Title</span></h1>
<div class="tiles">
<div class="important-links">
<h2>Important Links</h2>
<a href="#">We're Awesome</a>
<a href="#">Learn More</a>
<a href="#">Hire Us</a>
</div>
<div>
<h2>Our Logo</h2>
<img src="../../assets/fabric.jpg" width="100" alt="fabric logo" />
</div>
<div>
<h2>Contact Us</h2>
<div id="contact-form">
<label>Email</label><input type="email" />
<input value="Submit" type="submit" />
</div>
</div>
</div>
</div>
</body>
</html>

132
step1-02/demo/index.html Normal file
Просмотреть файл

@ -0,0 +1,132 @@
<html>
<body>
<div
class="codepen"
data-theme-id="36294"
data-prefill
data-editable="true"
data-height="100%"
data-theme-id="1"
data-default-tab="html,result"
>
<pre data-lang="css">
/* Targeting the entire page */
//body {
font: 1.2em sans-serif;
}
/* Targeting an HTML tag */
//h1 {
/* Color name */
color: black;
/* 6-digit hex */
background: #ababab;
/* Margin: specified separately for each side */
margin-bottom: 15px;
margin-top: 15px;
/* Shorthand: Padding applies to all sides */
padding: 10px;
/* Border shorthand and 3-digit hex */
border: 1px solid #ddd;
}
/* Overriding inherited styles */
//span {
color: #004578;
}
/* Sibling selector */
//a + a {
/* Changing elements from inline to block */
display: block;
}
/* Targeting a class name */
//.tiles {
display: flex;
}
/* Descendant selector */
//.tiles img {
width: 100%;
}
/* Direct descendant selector */
//.tiles > div {
/* rgb color */
background: rgb(10, 10, 10);
color: white;
flex-basis: 100%;
/* Padding/margin shorthand. Goes clockwise from top.
10px - all
10px 20px - top/bottom left/right
10px 20px 15px - top left/right bottom
*/
padding: 10px 20px 15px;
margin: 10px 20px 10px 0;
border: 1px solid white;
}
/* Qualified selector */
//div.important-links {
background: #004578;
}
/* Style inheritance only works for unstyled elements */
//a {
color: white;
}
/* Hover pseudo-selector */
//a:hover {
color: #ccc;
}
/* Positional pseudo-selector */
//.tiles > div:last-child {
/* overrides margin-right but leaves other margins alone */
margin-right: 0;
}
/* ID selector */
//#contact-form {
display: flex;
flex-direction: column;
}
/* Attribute selector */
//input[type='submit'] {
margin-top: 10px;
}
</pre>
<pre data-lang="html">
&lt;h1&gt;This is my &lt;span&gt;Title&lt;/span&gt;&lt;/h1&gt;
&lt;div class=&quot;tiles&quot;&gt;
&lt;div class=&quot;important-links&quot;&gt;
&lt;h2&gt;Important Links&lt;/h2&gt;
&lt;a href=&quot;#&quot;&gt;We're Awesome&lt;/a&gt;
&lt;a href=&quot;#&quot;&gt;Learn More&lt;/a&gt;
&lt;a href=&quot;#&quot;&gt;Hire Us&lt;/a&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;Our Logo&lt;/h2&gt;
&lt;img src=&quot;../../assets/fabric.jpg&quot; width=&quot;100&quot; alt=&quot;fabric logo&quot; /&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;h2&gt;Contact Us&lt;/h2&gt;
&lt;div id=&quot;contact-form&quot;&gt;
&lt;label&gt;Email&lt;/label&gt;&lt;input type=&quot;email&quot; /&gt;
&lt;input value=&quot;Submit&quot; type=&quot;submit&quot; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</pre>
</div>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
</body>
</html>

Просмотреть файл

@ -1,62 +0,0 @@
/* body {
font: 1.2em sans-serif;
} */
/* h1 {
color: black;
background: #ababab;
margin-bottom: 15px;
margin-top: 15px;
padding: 10px;
border: 1px solid #ddd;
} */
/* span {
color: #004578;
} */
/* a ~ a {
display: block;
} */
/* .tiles {
display: flex;
} */
/* .tiles img {
width: 100%;
} */
/* .tiles > div {
background: rgb(10, 10, 10);
color: white;
flex-basis: 100%;
padding: 10px 20px 15px;
margin: 10px 20px 10px 0;
border: 1px solid white;
} */
/* div.important-links {
background: #004578;
} */
/* a {
color: white;
} */
/* a:hover {
color: #ccc;
} */
/* .tiles > div:last-child {
margin-right: 0;
} */
/* #contact-form {
display: flex;
flex-direction: column;
} */
/* input[type='submit'] {
margin-top: 10px;
} */

Просмотреть файл

@ -0,0 +1,27 @@
h2 {
color: red;
}
h2 + div {
color: green;
}
.myList li {
border: 1px solid green;
}
.myClass {
background: green;
}
#myId {
background: yellow;
}
.myClass.otherClass {
color: white;
}
section > div:last-child {
border: 1px solid pink;
}

Просмотреть файл

@ -0,0 +1,56 @@
<html>
<body>
<div
class="codepen"
data-theme-id="36294"
data-prefill
data-editable="true"
data-height="100%"
data-theme-id="1"
data-default-tab="html,result"
>
<pre data-lang="css">
/* 1. */
/* 2. */
/* 3. */
/* 4. */
/* 5. */
/* 6. */
/* Bonus */
</pre>
<pre data-lang="html">
&lt;section&gt;
&lt;h2&gt;1. Text Color: Red&lt;/h2&gt;
&lt;div&gt;2. Color Green (hint: Sibling Selector)&lt;/div&gt;
&lt;ul class=&quot;myList&quot;&gt;
&lt;li&gt;
3. Border Green
&lt;/li&gt;
&lt;/ul&gt;
&lt;main&gt;
&lt;div class=&quot;myClass&quot;&gt;4. Background Green&lt;/div&gt;
&lt;div class=&quot;myClass otherClass&quot;&gt;
5. Background Green &amp; Color White
(Hint Qualified Selector)
&lt;/div&gt;
&lt;div id=&quot;myId&quot; class=&quot;otherClass&quot;&gt;6. Background Yellow&lt;/div&gt;
&lt;/main&gt;
&lt;ul&gt;
&lt;li&gt;
Don't Style Me
&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;Bonus: Border Pink&lt;/div&gt;
&lt;/section&gt;
</pre>
</div>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
</body>
</html>

Просмотреть файл

@ -52,11 +52,10 @@ let myFunction = function(myNumberParam) {
### Adding Variables
Let's start off our demo by adding some variables to our [script tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script). The other examples on this page will reference these variables.
Let's start off our demo by adding a variable to our [script tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script). This variable will be global and constant.
```js
const match = 'a';
let matches = 0;
```
## Functions
@ -65,6 +64,8 @@ Functions are reusable pieces of functionality. Functions can take inputs (param
In our example we'll create a function called `displayMatches` (camelCase is typical for functions) and we'll invoke this function every time that our submit button is clicked. For now we'll simply have our function call `alert("I'm Clicked")`, which is a function that creates an alert in your browser.
> Note that we want to place `matches` inside of the function so that it resets to 0 each time the function is called
```js
function displayMatches() {
alert("I'm Clicked");
@ -111,14 +112,14 @@ window.onclick = function() {
In our example we want to trigger a function based on the click of a button. To do this, we first need to get a reference to the button. We can use `querySelector` to get that reference. And then we can set its `onclick` value just like above.
```js
const button = docment.querySelector('.submit');
const button = document.querySelector('.submit');
button.onclick = displayMatches();
```
You can also combine these together like this:
```js
docment.querySelector('.submit').onclick = displayMatches();
docment.querySelector('.submit').onclick = displayMatches;
```
Wire this up and see you function in action!
@ -138,11 +139,12 @@ function displayMatches() {
## Conditionals
Next we want to compare each `letter` with our `match` value, and if they are the same, we will increment our `matches` variable. Remember that `letter = match` would set the `letter` variable to the value in `match`, so to do comparisons, we use the equality operator `==` or the strict equality operator `===`.
Next we want to compare each `letter` with our global `match` value, and if they are the same, we will increment a `matches` variable. Remember that `letter = match` would set the `letter` variable to the value in `match`, so to do comparisons, we use the equality operator `==` or the strict equality operator `===`.
```js
function displayMatches() {
const text = 'abcda';
let matches = 0;
for (let letter of text) {
if (letter === match) {
matches++;

Просмотреть файл

@ -1,19 +1,58 @@
<html>
<head>
<link rel="stylesheet" href="../css-demo/css-demo-final.css" />
</head>
<body>
<div>
<div class="tiles">
<div>
<h2>Contact Us</h2>
<div id="contact-form">
<label>Email</label><input id="email" type="email" />
<input class="submit" value="Submit" type="submit" />
</div>
</div>
</div>
<div
class="codepen"
data-theme-id="36294"
data-prefill
data-editable="true"
data-height="100%"
data-theme-id="1"
data-default-tab="js,result"
>
<pre data-lang="css">
body {
font: 1.2em sans-serif;
}
.tiles > div {
background: rgb(10, 10, 10);
color: white;
flex-basis: 100%;
padding: 10px 20px 15px;
margin: 10px 20px 10px 0;
border: 1px solid white;
}
#contact-form {
display: flex;
flex-direction: column;
}
input[type='submit'] {
align-self: flex-start;
margin-top: 10px;
}
</pre>
<pre data-lang="html">
&lt;div class=&quot;tiles&quot;&gt;
&lt;div&gt;
&lt;h2&gt;Contact Us&lt;/h2&gt;
&lt;div id=&quot;contact-form&quot;&gt;
&lt;label&gt;Email&lt;/label&gt;&lt;input id=&quot;email&quot; type=&quot;email&quot; /&gt;
&lt;input class=&quot;submit&quot; value=&quot;Submit&quot; type=&quot;submit&quot; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</pre>
<pre data-lang="js">
// Count the number of 'a' characters in the email form.
// Update button to reflect that number.
</pre
>
</div>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
</body>
<script></script>
</html>

Просмотреть файл

@ -0,0 +1,9 @@
1. Create a function named `getFavs` and set its contents to `alert('clicked')`
2. Create a variable `button` and set it to a reference to our button by using `document.querySelector('button')`
3. Add a click event listener to the button that calls `getFavs`. Click the button and make sure it calls our alert.
4. Replace the alert with a new `favList` variable set to an empty array: `[]`
5. Create a const variable `inputs` set to all of the inputs on the page. `querySelectorAll` will help here
6. Iterate over all of the inputs using `for (const input of inputs) {}`
7. For each iteration use an `if` statement to check if `input.checked` is equal to true
8. If the above tests passes, push the `input.parentNode.textContent` onto the `favList` array. Pass that text into `favList.push()` as the parameter to add it to the array
9. Outside of the for loop, use `document.querySelector('.favorites')` to target the div at the bottom of the page. Set the div's `textContent` to `favList.join(' ')`. This will join each of the foods together into a string separated by a space.

Просмотреть файл

@ -0,0 +1,14 @@
function getFavs() {
let favList = [];
const inputs = document.querySelectorAll('input');
for (const input of inputs) {
if (input.checked === true) {
favList.push(input.parentNode.textContent);
}
}
document.querySelector('.favorites').textContent = favList.join(' ');
}
let button = document.querySelector('button');
button.addEventListener('click', getFavs);

Просмотреть файл

@ -1,37 +1,48 @@
<html>
<style>
<body>
<div
class="codepen"
data-theme-id="36294"
data-prefill
data-editable="true"
data-height="100%"
data-theme-id="1"
data-default-tab="js,result"
>
<pre data-lang="css">
label,
button {
display: block;
margin-bottom: 10px;
}
</style>
<body>
<label><input type="checkbox" />Ice cream</label>
<label><input type="checkbox" />Pizza</label>
<label><input type="checkbox" />Tacos</label>
<label><input type="checkbox" />Meatloaf</label>
<label><input type="checkbox" />Brocolli</label>
</pre>
<pre data-lang="html">
&lt;label&gt;&lt;input type=&quot;checkbox&quot; /&gt;Ice cream&lt;/label&gt;
&lt;label&gt;&lt;input type=&quot;checkbox&quot; /&gt;Pizza&lt;/label&gt;
&lt;label&gt;&lt;input type=&quot;checkbox&quot; /&gt;Tacos&lt;/label&gt;
&lt;label&gt;&lt;input type=&quot;checkbox&quot; /&gt;Meatloaf&lt;/label&gt;
&lt;label&gt;&lt;input type=&quot;checkbox&quot; /&gt;Brocolli&lt;/label&gt;
<button>Display Your Favorites</button>
&lt;button&gt;Display Your Favorites&lt;/button&gt;
<div class="favorites"></div>
&lt;div class=&quot;favorites&quot;&gt;&lt;/div&gt;
</pre>
<pre data-lang="js">
/*
1. Create a function named `getFavs` and set its contents to `alert('clicked')`
2. Create a variable `button` and set it to a reference to our button by using `document.querySelector('button')`
3. Add a click event listener to the button that calls `getFavs`. Click the button and make sure it calls our alert.
4. Replace the alert with a new `favList` variable set to an empty array: `[]`
5. Create a const variable `inputs` set to all of the inputs on the page. `querySelectorAll` will help here
6. Iterate over all of the inputs using `for (const input of inputs) {}`
7. For each iteration use an `if` statement to check if `input.checked` is equal to true
8. If the above tests passes, push the `input.parentNode.textContent` onto the `favList` array. Pass that text into `favList.push()` as the parameter to add it to the array
9. Outside of the for loop, use `document.querySelector('.favorites')` to target the div at the bottom of the page. Set the div's `textContent` to `favList.join(' ')`. This will join each of the foods together into a string separated by a space.
*/
</pre>
</div>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
</body>
<script>
function getFavs() {
let favList = [];
const inputs = document.querySelectorAll('input');
for (const input of inputs) {
if (input.checked === true) {
favList.push(input.parentNode.textContent);
}
}
document.querySelector('.favorites').textContent = favList.join(' ');
}
let button = document.querySelector('button');
button.addEventListener('click', getFavs);
</script>
</html>

Просмотреть файл

@ -1,36 +1,10 @@
# Step 4 - Introduction To React Demo
In our last example we saw how we could take a static HTML page and turn it into an interactive page with some buttons and their `onclick` handlers.
In this example we'll see how React turns that paradigm completely around. With React, the entire DOM is generated and maintained by JavaScript, directly inside the browser. This makes it easier to assemble your application out of reusable pieces, maintain state within a component, and pass data between them.
In this demo we'll be creating a simple counter that will display a count and increment on click.
## Building the App
## React Hello World
If you already have the app running from a previous step, stop it with `ctrl+C`. Start the app version used in this step by running `npm start` from the root of the `frontend-bootcamp` folder. Click the "demo" link under day 1 step 4 to see results.
## index.html
The `index.html` file in a React project is going to be pretty mimimal. React is loading all of the application onto the page, so the only content you'll find in the page source is a div with an `id` of "app".
> Note that our bundling tool, webpack, is adding this script tag to the HTML file we provided
```html
<!DOCTYPE html>
<html>
<body>
<div id="app"></div>
<script src="../../step1-04/final/step1-04/final.js"></script>
</body>
</html>
```
## index.tsx
This is the entry point to your application.
```ts
```js
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(<p>Hello World</p>, document.getElementById('app'));
@ -90,9 +64,9 @@ export class App extends React.Component {
## Counter Component
In this example we'll start with an already scaffolded-out control. The goal of our counter is to track how many times the counter button is clicked. In the past JavaScript demo we might have accessed the counter element using `document.querySelector('.counter')` and manually incremented the number found there. While using the DOM as your data store works, it's REALLY hard to scale past the most basic demo.
In this example we'll start with an already scaffolded-out control. The goal of our counter is to track how many times the counter button is clicked.
React solves this by allowing each control to specify its own data store, called **state**. We can reference values in state when we render our UI, and we can also update state over the lifetime of our application.
React allows each control to specify its own data store, called **state**. We can reference values in state when we render our UI, and we can also update state over the lifetime of our application.
### Adding State
@ -205,11 +179,13 @@ This function will update our component's state, incrementing the counter value
```jsx
_onButtonClick = () => {
this.setState(prevState => ({ counter: prevState.counter + 1 }));
this.setState({
counter: this.state.counter + 1
});
};
```
> This isn't exactly a method, but a class property that is set to an [arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions). This mostly works the same as `onButtonClick() { }` but eliminates the need for [extra boilerplate](https://medium.freecodecamp.org/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb) used to avoid potential "gotchas" with [how `this` works in JavaScript](https://codeburst.io/javascript-the-keyword-this-for-beginners-fb5238d99f85).)
> Note that this could also be written as `this.setState(prevState => ({ counter: prevState.counter + 1 }));` to ensure that state is not updated until the previous state has been determined
Now that we have a function to increment our count, all that's left is to connect it to our button.
@ -217,11 +193,9 @@ Now that we have a function to increment our count, all that's left is to connec
<button onClick={this._onButtonClick}>Click</button>
```
> Note the syntax is a bit different than in HTML: `onclick="funcName()"` in HTML vs `onClick={this.funcName}` in JSX.
> Also note that each `Counter` maintains its own state! You can modify the state inside of one counter without affecting the others.
## Bonus: Using a Button component
## Using a Button component
Buttons are among the most commonly written components. Custom buttons help abstract common styling, add icons or other decorations, and increase functionality (menu buttons etc). Let's take a quick look at a custom button component to see how it comes together.

36
step1-05/TodoApp.html Normal file
Просмотреть файл

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<body>
<header>
<h1>todos</h1>
<div class="addTodo">
<input class="textfield" placeholder="add todo" />
<button class="submit">Add</button>
</div>
<nav class="filter">
<button class="selected">all</button>
<button>active</button>
<button>completed</button>
</nav>
</header>
<ul class="todos">
<li class="todo">
<label><input type="checkbox" /> Todo 1</label>
</li>
<li class="todo">
<label><input type="checkbox" /> Todo 2</label>
</li>
<li class="todo">
<label><input type="checkbox" /> Todo 3</label>
</li>
<li class="todo">
<label><input type="checkbox" /> Todo 4</label>
</li>
</ul>
<footer>
<span>4 items left</span>
<button class="submit">Clear Completed</button>
</footer>
</body>
</html>

Просмотреть файл

@ -1,7 +1,5 @@
# Building a Static Page
## Demo
To start off our todo application we are going to follow the steps outlined in [Thinking in React](https://reactjs.org/docs/thinking-in-react.html). The first step of the process is to break our application into a component hierarchy. For this app, we're going to keep it simple and just use four parts.
- TodoHeader
@ -9,38 +7,19 @@ To start off our todo application we are going to follow the steps outlined in [
- TodoListItem
- TodoFooter
We could go a lot deeper into creating buttons, inputs and checkboxes, but this is a great place to start. Often you'll want to start with a single large control and then break it up into smaller pieces.
You can find the HTML for our application in `step1-05/TodoApp.html`
### TodoApp
## TodoHeader
We are going to store all of our components inside of a `components` folder. Lets create that now. We'll then start with the `TodoHeader` inside of a file called `TodoHeader.tsx`. This file format tells our application that this file includes React code written in Typescript.
> We'll talk about Typescript soon, but for now know that all valid JavaScript is valid Typescript
```jsx
import React from 'react';
import { TodoFooter } from './components/TodoFooter';
import { TodoHeader } from './components/TodoHeader';
import { TodoList } from './components/TodoList';
export class TodoApp extends React.Component {
export class TodoHeader extends React.Component<any, any> {
render() {
return (
<div>
<TodoHeader />
<TodoList />
<TodoFooter />
</div>
);
}
}
```
We'll start off with all of the files scaffolded and imported into our App. This will let us dive right into each control and see updates quickly.
### TodoHeader
Our objective for now is to create a static version of our application, so we'll copy over the entire header tag from a previous step, minus any function calls we added.
> Note that since this is React we had to change `class` to `className`, but nothing else changes.
```jsx
return (
<header>
<h1>todos</h1>
@ -55,13 +34,21 @@ return (
</nav>
</header>
);
}
}
```
### TodoListItem
> Note that since this is React we had to change `class` to `className`, but nothing else changes.
## TodoListItem
Any time you see repeated complex elements, that is usually a sign that you should create a new component. With a few props you can typically abstract all of those elements into a single component. This is certainly the case with todo items.
```jsx
import React from 'react';
export class TodolistItem extends React.Component<any, any> {
render() {
return (
<li className="todo">
<label>
@ -69,6 +56,8 @@ return (
</label>
</li>
);
}
}
```
> Note that I've removed the title span as it was only needed to make targeting that text easier.
> Note that this control could also be created as a function instead of a class: `export const TodoListItem = (props) => {}`

Просмотреть файл

@ -1,15 +1,10 @@
import React from 'react';
import { TodoFooter } from './components/TodoFooter';
import { TodoHeader } from './components/TodoHeader';
import { TodoList } from './components/TodoList';
export class TodoApp extends React.Component<any, any> {
render() {
return (
<div>
<TodoHeader />
<TodoList />
<TodoFooter />
<p>Hello World</p>
</div>
);
}

Просмотреть файл

@ -1,9 +0,0 @@
import React from 'react';
export const TodoFooter = (props: any) => {
return (
<footer>
<div>Footer</div>
</footer>
);
};

Просмотреть файл

@ -1,11 +0,0 @@
import React from 'react';
export class TodoHeader extends React.Component<any, any> {
render() {
return (
<header>
<div>Header</div>
</header>
);
}
}

Просмотреть файл

@ -1,11 +0,0 @@
import React from 'react';
export class TodoList extends React.Component<any, any> {
render() {
return (
<div>
<span>List</span>
</div>
);
}
}

Просмотреть файл

@ -1,7 +0,0 @@
import React from 'react';
export class TodoListItem extends React.Component<any, any> {
render() {
return <div />;
}
}

Просмотреть файл

@ -1,14 +1,12 @@
## Exercise
If you already have the app running from a previous step, stop it with `ctrl+C`. Start the app version used in this step by running `npm start` from the root of the `frontend-bootcamp` folder. Click the "exercise" link under day 1 step 5 to see results.
### TodoFooter
1. Update the TodoFooter component, copying over the `<footer>` tag and all of its children
1. Add a TodoFooter component, copying over the `<footer>` tag and all of its children from `TodoApp.html` in the `step1-05` folder.
2. Remove any `onclick` properties, and change `class` to `className`
### TodoList
1. Update the TodoList component like you did with the footer.
1. Add a TodoList component like you did with the footer.
2. Import TodoListItem and add 4 of them inside of the `<ul>`
3. Bonus points for using a [`for`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration) loop or using [`map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) to create 4 list items based on the array `[1,2,3,4]`

Просмотреть файл

@ -46,7 +46,7 @@ constructor(props) {
To avoid reaching into state over and over, we once again use destructuring to pull out the pieces we need.
```jsx
const { filter, todos = [] } = this.state;
const { filter, todos } = this.state;
```
> Note that I've set `todos` to default to an empty array so that the `todos` variable is never undefined
@ -69,7 +69,7 @@ I've already pulled out our props into `filter` and `todos` variables, and writt
```jsx
{
filteredTodos.map(id => <TodoListItem key={id} id={id} {...todos[id]} />)
filteredTodos.map(id => <TodoListItem key={id} id={id} {...todos[id]} />);
}
```