mirror of
https://github.com/microsoft/frontend-bootcamp.git
synced 2026-01-26 14:56:42 +08:00
Day 1: title formatting coherence, other edits
This commit is contained in:
11
README.md
11
README.md
@@ -37,17 +37,12 @@ At this point, your VS Code window should look something like this:
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/1434956/53654442-9c379400-3c02-11e9-8768-d19e092b606d.png" width=500 />
|
||||
|
||||
To start the dev "inner loop" for the first three lessons, run:
|
||||
To start the dev "inner loop," run:
|
||||
```
|
||||
npm run static
|
||||
npm start
|
||||
```
|
||||
|
||||
When we get to lesson 4 and React, we'll stop the static inner loop (press `ctrl + C`) and instead run:
|
||||
```
|
||||
npm run start
|
||||
```
|
||||
|
||||
Both of these commands will load the site shown below.
|
||||
This will load the site shown below.
|
||||
|
||||
<img src="https://user-images.githubusercontent.com/1434956/53656239-88426100-3c07-11e9-8456-e3d958aa4def.png" width=500 />
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
# How the Web Works
|
||||
# Step 1.1 - Introduction to HTML (Demo)
|
||||
|
||||
## How the web works
|
||||
|
||||
A simple web page is rendered on the screen via the following steps.
|
||||
|
||||
@@ -21,7 +23,7 @@ A simple web page is rendered on the screen via the following steps.
|
||||
|
||||

|
||||
|
||||
# HTML Demo
|
||||
## HTML demo
|
||||
|
||||
HTML tags are the basis of all web applications. They give the page structure and define the content within.
|
||||
|
||||
@@ -35,7 +37,7 @@ HTML tags can also be nested to create a tree that we call the [Document Object
|
||||
|
||||
The [HTML demo page](https://microsoft.github.io/frontend-bootcamp/step1-01/demo) shows a large collection of HTML elements that you will come across during development. The full list of elements can be found on [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
|
||||
|
||||
## Sample Website
|
||||
## Sample webpage
|
||||
|
||||
```html
|
||||
<html>
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
Readme is in index.html
|
||||
# Step 1.1 - Introduction to HTML (Exercise)
|
||||
|
||||
See index.html from [npm start](http://localhost:8080/step1-01/exercise/) or the [live site](https://microsoft.github.io/frontend-bootcamp/step1-01/exercise/) for the exercise.
|
||||
@@ -1,6 +1,6 @@
|
||||
## CSS Demo
|
||||
# Step 1.2 - Introduction to CSS (Demo)
|
||||
|
||||
### CSS Properties
|
||||
## CSS properties
|
||||
|
||||
Now that we've gone over adding HTML tags to the page, let's cover adding styles to those tags. We can do quite a lot with styles! We can change:
|
||||
|
||||
@@ -15,7 +15,7 @@ Now that we've gone over adding HTML tags to the page, let's cover adding styles
|
||||
|
||||
CSS styles are always written in `property: value` pairs (like `background: blue;`) and terminated with a semicolon.
|
||||
|
||||
### Applying CSS to an HTML file
|
||||
## Applying CSS to an HTML file
|
||||
|
||||
CSS can be applied to HTML tags in three different ways.
|
||||
|
||||
@@ -25,7 +25,7 @@ CSS can be applied to HTML tags in three different ways.
|
||||
3. Through an external CSS file
|
||||
- `<link rel="stylesheet" href="./css-demo-finished.css" />`
|
||||
|
||||
### Targeting specific elements
|
||||
## Targeting specific elements
|
||||
|
||||
Inline styles are always applied directly to the element you place them on, but `<style>` tags and external CSS files need a way to match elements with their respective style sets. This is done with **[CSS selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Selectors)**. When selectors are combined with CSS styles, we call this a **ruleset**.
|
||||
|
||||
3
step1-02/exercise/README.md
Normal file
3
step1-02/exercise/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Step 1.2 - Introduction to CSS (Exercise)
|
||||
|
||||
See index.html from [npm start](http://localhost:8080/step1-02/exercise/) or the [live site](https://microsoft.github.io/frontend-bootcamp/step1-02/exercise/) for the exercise.
|
||||
@@ -10,22 +10,22 @@
|
||||
data-default-tab="html,result"
|
||||
>
|
||||
<pre data-lang="css">
|
||||
/* 1. */
|
||||
/* 1. */
|
||||
|
||||
/* 2. */
|
||||
/* 2. */
|
||||
|
||||
/* 3. */
|
||||
/* 3. */
|
||||
|
||||
/* 4. */
|
||||
|
||||
/* 5. */
|
||||
/* 5. */
|
||||
|
||||
/* 6. */
|
||||
/* 6. */
|
||||
|
||||
/* Bonus */
|
||||
</pre>
|
||||
<pre data-lang="html">
|
||||
<!-- Without changing the below markup apply the styles asked for in the markup. Do not apply styles that a tag doesn't ask for -->
|
||||
<!-- Without changing the HTML markup, apply the styles asked for in the markup. Do not apply styles that a tag doesn't ask for. -->
|
||||
|
||||
<section>
|
||||
<h2>1. Text Color: Red</h2>
|
||||
@@ -38,7 +38,7 @@
|
||||
</ul>
|
||||
<div class="myClass">4. Background Green</div>
|
||||
<div class="myClass otherClass">
|
||||
5. Background Green & Color White
|
||||
5. Background Green & Color White
|
||||
(Hint Qualified Selector)
|
||||
</div>
|
||||
<div id="myId" class="otherClass">6. Background Yellow</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# JavaScript Demo
|
||||
# Step 1.3 - Introduction to JavaScript (Demo)
|
||||
|
||||
It's entirely possible to create a website with nothing but HTML and CSS, but as soon as you want user interaction other than links and forms, you'll need to reach for JavaScript, the scripting language of the web. Fortunately, JavaScript has grown up quite a bit since it was introduced in the '90s, and now runs just about everything: web applications, mobile applications, native applications, servers, robots and rocket ships.
|
||||
|
||||
@@ -20,7 +20,7 @@ By the end of the demo we'll have covered the following:
|
||||
- Loops
|
||||
- Interacting with the DOM (Document Object Model)
|
||||
|
||||
## Introduction To Variables
|
||||
## Introduction to variables
|
||||
|
||||
We can create a new variable with the keywords `var`, `let`, `const` and use them within our application. These variables can contain one of the following types of values:
|
||||
|
||||
@@ -35,7 +35,7 @@ We can create a new variable with the keywords `var`, `let`, `const` and use the
|
||||
|
||||
> [When to use `var`/`let`/`const`?](https://stackoverflow.com/questions/762011/whats-the-difference-between-using-let-and-var-to-declare-a-variable-in-jav) Use `const` for variables you never expect to change, and `let` for anything else. `var` is mostly no longer used. See the link for more details about how each works.
|
||||
|
||||
### Variable Examples
|
||||
### Variable examples
|
||||
|
||||
```js
|
||||
const myBoolean = true;
|
||||
@@ -50,7 +50,7 @@ const myFunction = function(myNumberParam) {
|
||||
|
||||
> JavaScript is a dynamically typed language, so if you initially store a number in a variable (`let myVar = 0`), you can change it to contain a string by simply writing `myVar = 'hello'` without any trouble.
|
||||
|
||||
### Adding Variables
|
||||
### Adding 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.
|
||||
|
||||
@@ -76,7 +76,7 @@ Functions on their own don't have any effect on the page. When I declare `functi
|
||||
|
||||
To execute a function we need to attach it to an event. There are a number of possible events: keyboard strokes, mouse clicks, document loading, and more.
|
||||
|
||||
### Add Event Listeners
|
||||
### Add event listeners
|
||||
|
||||
To attach a function to an event, we use an [`addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventListener) like this:
|
||||
|
||||
@@ -92,7 +92,7 @@ window.addEventListener('click', function() {
|
||||
|
||||
> [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) is a reference to the entire window containing the HTML document.
|
||||
|
||||
### Global Event Handlers
|
||||
### Global event handlers
|
||||
|
||||
If you think this feels a little verbose, you're not alone. Many of the [most common event types](https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers) are available as element properties. This way we can set properties like `onload` or `onclick` like this:
|
||||
|
||||
@@ -208,7 +208,3 @@ function displayMatches() {
|
||||
document.querySelector('.submit').value = matches + ' matches';
|
||||
}
|
||||
```
|
||||
|
||||
## Next Step
|
||||
|
||||
[Start our Todo App](../../step1-02/demo/)
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
# Exercise
|
||||
# Step 1.3 - Introduction to JavaScript (Exercise)
|
||||
|
||||
1. Create a function named `getFavs`. Inside, run `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 the alert is displayed.
|
||||
4. Replace the `alert` call 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`](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll) will help here.
|
||||
6. Iterate over all of the inputs using `for (const input of inputs) {}`
|
||||
7. In 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 by passing the text as a parameter to `favList.push()` ([`push](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push) is a built-in array method.)
|
||||
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.
|
||||
See index.html from [npm start](http://localhost:8080/step1-03/exercise/) or the [live site](https://microsoft.github.io/frontend-bootcamp/step1-03/exercise/) for the exercise.
|
||||
@@ -28,16 +28,33 @@ button {
|
||||
<div class="favorites"></div>
|
||||
</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.
|
||||
/*
|
||||
1. Create a function named `getFavs`. Inside, run:
|
||||
alert('clicked')
|
||||
|
||||
2. Create a variable `button` and set it to a reference to our button using:
|
||||
document.querySelector('button')
|
||||
|
||||
3. Add a click event listener to the button that calls `getFavs`.
|
||||
Click the button and make sure the alert is displayed.
|
||||
|
||||
4. Replace the `alert` call 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. In 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` into the `favList`
|
||||
array by passing the text as a parameter to `favList.push()`
|
||||
- `push` is a built-in array method: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push
|
||||
|
||||
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>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Step 4 - Introduction To React Demo
|
||||
# Step 1.4 - Introduction to React (Demo)
|
||||
|
||||
In this demo we'll be creating a simple counter that will display a count and increment on click.
|
||||
|
||||
@@ -19,7 +19,7 @@ The first parameter to `render()` looks a lot like HTML, but actually, it's [JSX
|
||||
- Controls can be self-closing: `<MyControl text='hi' />`
|
||||
- You can use JavaScript inside of JSX!
|
||||
|
||||
## Writing a React Component
|
||||
## Writing a React component
|
||||
|
||||
A React component is a piece of code that returns a portion of your application. This can include HTML markup, CSS styles, and JavaScript driven functionality.
|
||||
|
||||
@@ -87,7 +87,7 @@ const App = props => {
|
||||
};
|
||||
```
|
||||
|
||||
### Destructuring Props
|
||||
### Destructuring props
|
||||
|
||||
Writing `props.text` over and over in a function (or `this.props.text` in a class) can be quite tedious. Since this is all JavaScript, you could create a new variable for this text using variable assignment.
|
||||
|
||||
@@ -159,13 +159,13 @@ ReactDOM.render(<App />, document.getElementById('app'));
|
||||
|
||||
> Note the capitalization of `Counter`. HTML might not be case-sensitive, but JSX is! A common practice is to use the capitalized names of HTML elements to name corresponding React components: Button, Select, Label, Form, etc.
|
||||
|
||||
## React State
|
||||
## Writing a stateful Counter component
|
||||
|
||||
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.
|
||||
|
||||
> Most stateful components you'll see today will be `class` based. It is just recently possible to add state to function components through the use of [`hooks`](https://reactjs.org/docs/hooks-intro.html)
|
||||
|
||||
### Adding State
|
||||
### Adding state
|
||||
|
||||
JavaScript classes use a `constructor` method to instantiate each copy of a class, along with any applicable state. Let's create a new component called `Counter` and give it a state containing a `clicks` property with a default value of `0`;
|
||||
|
||||
@@ -184,7 +184,7 @@ class Counter extends React.Component {
|
||||
- The [`super()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/super) function calls the constructor of the parent class (in this case `React.Component`).
|
||||
- Our `counter` state value can now be accessed via `this.state.counter`. Later, we can update state by calling `this.setState({ counter: 1 })`.
|
||||
|
||||
### Creating our Counter
|
||||
### Rendering our Counter
|
||||
|
||||
For our `Counter` component, the goal is to be able to track how many times the counter's button is clicked. We'll use the following markup.
|
||||
|
||||
@@ -201,7 +201,7 @@ render() {
|
||||
}
|
||||
```
|
||||
|
||||
### Writing our Button Click Handler
|
||||
### Writing our button click handler
|
||||
|
||||
Our next step is to wire up the button to increment the `counter` in our component state.
|
||||
|
||||
@@ -235,11 +235,11 @@ Add a couple `Counter`s to our `App`, each with different text. Notice how they
|
||||
|
||||
## Moving this into our codebase
|
||||
|
||||
To scale our application we'll need to break up the file into smaller, reusable pieces. In this part of the demo we'll look at the `final` folder and how the JavaScript module system allows us to break up our components into a collection of files exporting their functionality.
|
||||
To scale our application, we'll need to break up the file into smaller, reusable pieces. In this part of the demo we'll look at the `final` folder and how the JavaScript module system allows us to break up our components into a collection of files exporting their functionality.
|
||||
|
||||
### Module Exports and Imports
|
||||
### Module exports and imports
|
||||
|
||||
Open up the `step1-04/final/components/Counter.tsx` and look at the `Counter` component.
|
||||
Open up `step1-04/final/components/Counter.tsx` and look at the `Counter` component.
|
||||
|
||||
```tsx
|
||||
export class Counter extends React.Component {
|
||||
@@ -255,7 +255,7 @@ import { Counter } from './components/Counter';
|
||||
|
||||
> Note the `{}` wrapped around the import value. This is actually an example of destructuring.
|
||||
|
||||
#### Default Exports
|
||||
#### Default exports
|
||||
|
||||
We typically use named exports, but it's also possible export a default value like this:
|
||||
|
||||
@@ -271,7 +271,7 @@ When we import the component we can call it whatever we want:
|
||||
import SomeCounterComponent from './components/Counter';
|
||||
```
|
||||
|
||||
## Using a Button component
|
||||
## Writing 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.
|
||||
|
||||
|
||||
3
step1-04/final/README.md
Normal file
3
step1-04/final/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Step 1.4 - Introduction to React (Final)
|
||||
|
||||
Take a look at the contents of the `src` folder to see final versions of the `App`, `Button`, and `Counter` components from this lesson.
|
||||
@@ -1,19 +1,19 @@
|
||||
# Step 1-05: Demo Building a Static Page
|
||||
# Step 1.5 - Building a static page in React (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.
|
||||
To start building our todo application, we'll 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
|
||||
- TodoList
|
||||
- TodoListItem
|
||||
- TodoFooter
|
||||
|
||||
You can find the HTML for our application in `step1-05/TodoApp.html`
|
||||
You can find the HTML for our application in `step1-05/TodoApp.html`.
|
||||
|
||||
## 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 store all of our components inside a `components` folder under `src`. Let's create that now. We'll then start writing the `TodoHeader` in `components/src/TodoHeader.tsx`. The `tsx` file extension tells our editor 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
|
||||
> We'll talk about TypeScript soon, but for now, know that all valid JavaScript is valid TypeScript.
|
||||
|
||||
```jsx
|
||||
import React from 'react';
|
||||
@@ -38,7 +38,7 @@ export class TodoHeader extends React.Component<any, any> {
|
||||
}
|
||||
```
|
||||
|
||||
> Note that since this is React we had to change `class` to `className`, but nothing else changes.
|
||||
> Note that since this is React, we had to change `class` to `className`, but nothing else changes.
|
||||
|
||||
## TodoListItem
|
||||
|
||||
@@ -60,4 +60,15 @@ export class TodolistItem extends React.Component<any, any> {
|
||||
}
|
||||
```
|
||||
|
||||
> Note that this control could also be created as a function instead of a class: `export const TodoListItem = (props) => {}`
|
||||
> Note that this control could also be created as a function instead of a class:
|
||||
> ```jsx
|
||||
> export const TodoListItem = (props) => {
|
||||
> return (
|
||||
> <li className="todo">
|
||||
> <label>
|
||||
> <input type="checkbox" /> Todo 1
|
||||
> </label>
|
||||
> </li>
|
||||
> );
|
||||
> }
|
||||
> ```
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
# Step 1-06 Exercise
|
||||
# Step 1.5 - Building a static page in React (Exercise)
|
||||
|
||||
### TodoFooter
|
||||
From this exercise on, we'll be working in VS Code instead of CodePen. If you don't already have the bootcamp folder open in a VS Code window, see the [main readme](https://github.com/Microsoft/frontend-bootcamp/blob/master/README.md) for instructions.
|
||||
|
||||
1. Add a TodoFooter component in the `components` folder, copying over the `<footer>` tag and all of its children from `TodoApp.html` in the `step1-05` folder. This could be a function or class.
|
||||
If you don't already have the app running, start it 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. Add a TodoFooter component in the `components` folder, copying over the `<footer>` tag and all of its children from `TodoApp.html` in the `step1-05` folder. This component could be a function or class.
|
||||
2. Remove any `onclick` properties, and change `class` to `className`
|
||||
|
||||
### TodoList
|
||||
## TodoList
|
||||
|
||||
1. Add a TodoList component like you did with the footer. This could also be function or class.
|
||||
2. Import TodoListItem and add 4 of them inside of the `<ul>`
|
||||
2. Import TodoListItem and add four 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]`
|
||||
|
||||
## App.tsx
|
||||
## App
|
||||
|
||||
1. Import both of these components into `App.tsx` and place their tags below the `TodoHeader`.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# Step 1-06 Demo: Creating a State-Driven UI
|
||||
# Step 1.6 - Creating a state-driven UI (Demo)
|
||||
|
||||
In React, the data travels in one direction: top-down in the form of state propagating down the component hierarchy. Only the component containing the state can change the state itself. When a UI interaction occurs, a stateful component must pass down an event handler to the UI component triggering the event in order to signal a state change.
|
||||
|
||||
[Step #3 of "Thinking in React"](https://reactjs.org/docs/thinking-in-react.html) suggests finding the "minimal set of mutable state" that your application requires. So in this demo we are going to add that "minimal state" to our application and drive our UI off of that data. With that done, the next step will be to create ways to modify that state, which will in turn cascade down through our UI. This [reconciliation](https://reactjs.org/docs/reconciliation.html) process, figuring out what in your UI needs to change based on changing state, is what React excels at.
|
||||
|
||||
## Adding State to `TodoApp.tsx`
|
||||
## Adding state to TodoApp
|
||||
|
||||
Inside our `TodoApp` class, we will add the minimal state for our application, which includes just two keys: `todos` and `filter`. We don't need to worry about a `remaining` value because it can be calculated by counting the number of todos where the `completed` field is set to `false`.
|
||||
Inside our `TodoApp` class, we will add the minimal state for our application, which includes just two keys: `todos` and `filter`. We don't need to worry about a `remaining` count because it can be calculated by counting the number of todos where the `completed` field is set to `false`.
|
||||
|
||||
So here is our full constructor:
|
||||
|
||||
@@ -39,7 +39,7 @@ constructor(props) {
|
||||
|
||||
> You could also use an array to represent your todos. Array manipulation can be easier in some cases, but this object approach simplifies other functionality and will ultimately be more performant.
|
||||
|
||||
## Passing State Through to UI
|
||||
## Passing state through to UI
|
||||
|
||||
Now we can pass `filter` and `todos` into our components.
|
||||
|
||||
@@ -56,7 +56,7 @@ render() {
|
||||
}
|
||||
```
|
||||
|
||||
## State-Driven TodoList
|
||||
## State-driven TodoList
|
||||
|
||||
I've already pulled out our props into `filter` and `todos` variables, and written a bit of JS that will return an array of filtered todo `id`s. We'll be using that filtered array to render our todo items.
|
||||
|
||||
@@ -72,11 +72,11 @@ return (
|
||||
);
|
||||
```
|
||||
|
||||
## State-Driven and Stateful Header
|
||||
## State-driven and stateful TodoHeader
|
||||
|
||||
Within the header we've got a situation where we not only want to pass `filter` state down to it, but we also want to maintain state within the control. Fortunately, this is no problem at all for React. First off let's deal with the incoming state.
|
||||
Within the header, we've got a situation where we not only want to pass `filter` state down to it, but we also want to maintain state within the control. Fortunately, this is no problem at all for React. First off let's deal with the incoming state.
|
||||
|
||||
### Conditional Class Names
|
||||
### Conditional class names
|
||||
|
||||
In CSS-based styling, visual states are applied by adding and removing classes. We can use the filter value to conditionally add a class, thereby lighting up the correct filter button.
|
||||
|
||||
@@ -90,7 +90,7 @@ In CSS-based styling, visual states are applied by adding and removing classes.
|
||||
|
||||
> The [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) `condition ? expressionIfTrue : expressionIfFalse` is widely used in React code, as each expression could be a string for a className or even a JSX element.
|
||||
|
||||
### Adding a Controlled Input
|
||||
### Adding a controlled input
|
||||
|
||||
In React, form elements such as `<input>`, `<textarea>`, and `<select>` can be used as either **uncontrolled** or **controlled**.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
## Exercise
|
||||
# Step 1.6 - Creating a state-driven UI (Exercise)
|
||||
|
||||
If you don't already have the app running, start it by running `npm start` from the root of the `frontend-bootcamp` folder. Click the "exercise" link under day 1 step 6 to see results.
|
||||
|
||||
### TodoFooter
|
||||
|
||||
1. Use the provided `itemCount` value to display the current number of items left.
|
||||
2. Use a ternary operator to print "item" vs "item**s**" based on whether `itemCount === 1`.
|
||||
2. Use a [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator) to print "item" vs "item**s**" based on whether `itemCount === 1`.
|
||||
|
||||
### TodoListItem
|
||||
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
# Types and Creating a UI-Driven State
|
||||
# Step 1.7 - Types and creating a UI-driven state (Demo)
|
||||
|
||||
Now that we have a UI that is purely driven by the state of our app, we need to add functionality to allow the UI to drive the state. This is often done by creating functions that call `setState` like we saw in the `TodoHeader`. Values from the state are then passed down to the UI as props.
|
||||
Now that we have a UI that is purely driven by the state of our app, we need to add functionality to allow the UI to drive the state. This is often done by creating functions that call `setState` like we saw in the `TodoHeader`. Values from the state are then passed down child components as props.
|
||||
|
||||
> We'll be learning in part 2 of this workshop how we can expose these functions without explicitly passing them down via props.
|
||||
|
||||
This is our core "business logic" and handles everything our basic "CRUD" operations: Create, Read, Update, Delete. We don't have time to walk through writing all of those functions, but you can see that they are already provided in the demo's `TodoApp` and passed into our components.
|
||||
This is our core "business logic" and handles our basic "CRUD" operations: Create, Read, Update, Delete. We don't have time to walk through writing all of those functions, but you can see that they are already provided in the demo's `TodoApp` and passed into our components.
|
||||
|
||||
## Intro to TypeScript
|
||||
|
||||
Taking a look at our components in `TodoApp`, you can see that our list of props is not just getting longer, but is getting much more complex! We're passing through functions with various signatures, complex `todos` objects, and filter strings which are always one of three values.
|
||||
Taking a look at our components in `TodoApp`, you can see that our list of props is getting not just longer, but much more complex! We're passing through functions with various signatures, complex `todos` objects, and filter strings which are always one of three values.
|
||||
|
||||
As applications grow, it becomes increasing difficult to remember what each function does, or what each todo contains. Also, as JavaScript is a dynamically typed language, if I wanted to change the value of `todos` to an array inside my `TodoList`, JavaScript wouldn't care. But if `TodoListItems` was expecting an object, our application would break.
|
||||
As applications grow, it becomes difficult to remember what each function does or what each todo contains. Also, as JavaScript is a dynamically typed language, if I wanted to change the value of `todos` to an array inside my `TodoList`, JavaScript wouldn't care. But if `TodoListItems` was expecting an object, our application would break.
|
||||
|
||||
It for these two reasons that the entire industry is shifting to writing applications that are strongly typed, and many are using TypeScript to accomplish that.
|
||||
For these two reasons, the industry is shifting to writing applications that are strongly typed, and many are using TypeScript to accomplish that.
|
||||
|
||||
As [TypeScript's website](https://www.typescriptlang.org/) states:
|
||||
|
||||
> TypeScript is a superset of JavaScript that compiles to plain JavaScript.
|
||||
|
||||
If you've ever used [Sass](https://sass-lang.com/) you are familiar with this concept. In the same way that all valid CSS is valid Sass, all valid JavaScript is valid TypeScript. That's why most of these exercises have been written in `ts` and `tsx` files instead of `js` and `jsx` files.
|
||||
If you've used [Sass](https://sass-lang.com/), you're familiar with this concept. In the same way that all valid CSS is valid Sass, all valid JavaScript is valid TypeScript. That's why our exercises have been written in `ts` and `tsx` files instead of `js` and `jsx`.
|
||||
|
||||
Let's dive into the demo and see how TypeScript can help us better understand our component props and guard against future regressions.
|
||||
Let's dive in and see how TypeScript can help clarify our component props and guard against future regressions.
|
||||
|
||||
# Demo
|
||||
|
||||
Let's start off in the TodoList, as that has the most data flow up and down. There isn't any interactive UI in this component, as we're simply passing `completed` down to each `TodoListItem`, but we can write a props interface for the component to make sure that everything gets passed down properly.
|
||||
Let's start off in the TodoList, as that has the most data flow up and down. There isn't any interactive UI in this component, as we're simply passing `completed` down to each `TodoListItem`, but we can write a props interface to make sure that everything gets passed down properly.
|
||||
|
||||
## Writing TodoListProps
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#Step 1-07: Exercise
|
||||
# Step 1.7 - Types and creating a UI-driven state (Exercise)
|
||||
|
||||
If you don't already have the app running, start it by running `npm start` from the root of the `frontend-bootcamp` folder. Click the "exercise" link under day 1 step 7 to see results.
|
||||
|
||||
## TodoFooter
|
||||
|
||||
1. Open TodoFooter and write a TodoFooterProps interface. It should include two values, a `clear` and `todos`. Use this interface in the function props like this: `(props: TodoFooterProps)`
|
||||
1. Open TodoFooter and write a `TodoFooterProps` interface. It should include two values, a `clear` and `todos`. Use this interface in the function props like this: `(props: TodoFooterProps)`
|
||||
|
||||
2. Write an `_onClick` function that calls `props.clear`.
|
||||
|
||||
> Since TodoFooter is not a class, the `_onClick` function needs to be stored in a const placed before the `return`.
|
||||
- Since TodoFooter is not a class, the `_onClick` function needs to be stored in a const placed before the `return`.
|
||||
- Remember to use an arrow function to define this click handler.
|
||||
|
||||
3. Assign `_onClick` to the button's `onClick` prop. You won't need to use `this` since the component isn't a class.
|
||||
|
||||
@@ -14,13 +17,14 @@
|
||||
|
||||
## TodoHeader
|
||||
|
||||
1. Open TodoHeader and write TodoHeaderProps which will include `addTodo`, `setFilter` and `filter`. Replace the first `any` in the class declaration with this interface.
|
||||
1. Open TodoHeader and write `TodoHeaderProps` which will include `addTodo`, `setFilter` and `filter`. Replace the first `any` in the class declaration with this interface.
|
||||
|
||||
2. This component also has state. Write TodoHeaderState (there's just one value), and add this where the second `any` was.
|
||||
2. This component also has state. Write `TodoHeaderState` (there's just one value), and add this where the second `any` was.
|
||||
|
||||
3. Add `_onFilter` to each of the filter buttons
|
||||
|
||||
> Note that we can't add new parameters to onClick, but we can pull information from the event target!
|
||||
- Note that we can't add new parameters to onClick, but we can pull information from the event target!
|
||||
- Remember to use an arrow function for this one too
|
||||
|
||||
4. Call `_onAdd` from the submit button
|
||||
|
||||
|
||||
Reference in New Issue
Block a user