11 | In React apps, we write JSX - it looks like HTML, and uses a lot of HTML
12 | syntax. JSX lets us include JavaScript functions right along with the
13 | HTML, and also allows us to add in components, which are separate,
14 | self-contained chunks of JSX.
15 |
16 |
17 |
18 | );
19 | }
20 |
21 | export default App;
22 |
--------------------------------------------------------------------------------
/.github/workflows/canvas-sync-html.yml:
--------------------------------------------------------------------------------
1 | # Secret stored in learn-co-curriculum Settings/Secrets
2 |
3 | name: Sync with Canvas HTML
4 |
5 | on:
6 | push:
7 | branches: [master, main]
8 | paths:
9 | - "README.md"
10 |
11 | jobs:
12 | sync:
13 | name: Sync with Canvas
14 |
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 |
20 | - name: Set up Ruby
21 | uses: ruby/setup-ruby@v1
22 | with:
23 | ruby-version: 2.7
24 |
25 | - name: Install github-to-canvas
26 | run: gem install github-to-canvas
27 |
28 | - name: Sync from .canvas file
29 | run: github-to-canvas -a -lr --forkable --contains-html
30 | env:
31 | CANVAS_API_KEY: ${{ secrets.CANVAS_API_KEY }}
32 | CANVAS_API_PATH: ${{ secrets.CANVAS_API_PATH }}
33 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/node
2 |
3 | ### Node ###
4 | # Logs
5 | logs
6 | *.log
7 | npm-debug.log*
8 |
9 | # Runtime data
10 | pids
11 | *.pid
12 | *.seed
13 |
14 | # Directory for instrumented libs generated by jscoverage/JSCover
15 | lib-cov
16 |
17 | # Coverage directory used by tools like istanbul
18 | coverage
19 |
20 | # nyc test coverage
21 | .nyc_output
22 |
23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24 | .grunt
25 |
26 | # node-waf configuration
27 | .lock-wscript
28 |
29 | # Compiled binary addons (http://nodejs.org/api/addons.html)
30 | build/Release
31 |
32 | # Dependency directories
33 | node_modules
34 | jspm_packages
35 |
36 | # Optional npm cache directory
37 | .npm
38 |
39 | # Optional REPL history
40 | .node_repl_history
41 |
42 | # Learn-specific .results.json
43 | .results.json
44 |
45 | # Ignore Yarn lock
46 | yarn.lock
47 |
48 | # Ignore DS_STORE
49 | .DS_Store
50 |
51 | # Ignore ESLint files
52 | .eslintcache
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-hooks-app-example",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "date-fns": "^2.16.1",
7 | "react": "^17.0.1",
8 | "react-dom": "^17.0.1",
9 | "react-scripts": "4.0.1"
10 | },
11 | "devDependencies": {
12 | "@learn-co-curriculum/jest-learn-reporter": "^0.1.0",
13 | "@testing-library/jest-dom": "^5.11.4",
14 | "@testing-library/react": "^11.1.0",
15 | "@testing-library/user-event": "^12.1.10",
16 | "mocha": "^8.2.1"
17 | },
18 | "scripts": {
19 | "start": "react-scripts start",
20 | "build": "react-scripts build",
21 | "test": "echo \".results.json\" && react-scripts test --reporters=@learn-co-curriculum/jest-learn-reporter --reporters=default --watchAll",
22 | "eject": "react-scripts eject"
23 | },
24 | "eslintConfig": {
25 | "extends": [
26 | "react-app",
27 | "react-app/jest"
28 | ]
29 | },
30 | "browserslist": {
31 | "production": [
32 | ">0.2%",
33 | "not dead",
34 | "not op_mini all"
35 | ],
36 | "development": [
37 | "last 1 chrome version",
38 | "last 1 firefox version",
39 | "last 1 safari version"
40 | ]
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/__tests__/App.test.js:
--------------------------------------------------------------------------------
1 | import "@testing-library/jest-dom";
2 | import { render, screen } from "@testing-library/react";
3 | import { format } from "date-fns";
4 | import App from "../components/App";
5 |
6 | beforeEach(() => {
7 | render();
8 | });
9 |
10 | test('should include "Now" in the header instead of a time', () => {
11 | expect(
12 | screen.queryByText(format(new Date(), "MMMM do yyyy, h:mm:ss a"))
13 | ).not.toBeInTheDocument();
14 | expect(screen.queryByText(/Now/g)).toBeInTheDocument();
15 | });
16 |
17 | test("should include the ", () => {
18 | expect(screen.queryByText("Whoa!")).toBeInTheDocument();
19 | });
20 |
21 | test("should include the ", () => {
22 | expect(screen.queryByTitle("time video")).toBeInTheDocument();
23 | });
24 |
25 | // it('should include "Now" in the header instead of a time', () => {
26 | // expect(wrapper.find('header').text()).to.not.include(moment().format('MMMM Do YYYY'))
27 | // expect(wrapper.find('header').text()).to.include('Now')
28 | // });
29 |
30 | // it('should include the ExampleComponent', () => {
31 | // expect(wrapper.text()).to.include('')
32 | // });
33 |
34 | // it('should include the TestComponent', () => {
35 | // expect(wrapper.text()).to.include('')
36 | // });
37 | // });
38 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # Learn.co Educational Content License
2 |
3 | Copyright (c) 2015 Flatiron School, Inc
4 |
5 | The Flatiron School, Inc. owns this Educational Content. However, the Flatiron
6 | School supports the development and availability of educational materials in
7 | the public domain. Therefore, the Flatiron School grants Users of the Flatiron
8 | Educational Content set forth in this repository certain rights to reuse, build
9 | upon and share such Educational Content subject to the terms of the Educational
10 | Content License set forth [here](http://learn.co/content-license)
11 | (http://learn.co/content-license). You must read carefully the terms and
12 | conditions contained in the Educational Content License as such terms govern
13 | access to and use of the Educational Content.
14 |
15 | Flatiron School is willing to allow you access to and use of the Educational
16 | Content only on the condition that you accept all of the terms and conditions
17 | contained in the Educational Content License set forth
18 | [here](http://learn.co/content-license) (http://learn.co/content-license). By
19 | accessing and/or using the Educational Content, you are agreeing to all of the
20 | terms and conditions contained in the Educational Content License. If you do
21 | not agree to any or all of the terms of the Educational Content License, you
22 | are prohibited from accessing, reviewing or using in any way the Educational
23 | Content.
24 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Learn.co Curriculum
2 |
3 | We're really exited that you're about to contribute to the [open
4 | curriculum](https://learn.co/content-license) on [Learn.co](https://learn.co).
5 | If this is your first time contributing, please continue reading to learn how
6 | to make the most meaningful and useful impact possible.
7 |
8 | ## Raising an Issue to Encourage a Contribution
9 |
10 | If you notice a problem with the curriculum that you believe needs improvement
11 | but you're unable to make the change yourself, you should raise a Github issue
12 | containing a clear description of the problem. Include relevant snippets of
13 | the content and/or screenshots if applicable. Curriculum owners regularly review
14 | issue lists and your issue will be prioritized and addressed as appropriate.
15 |
16 | ## Submitting a Pull Request to Suggest an Improvement
17 |
18 | If you see an opportunity for improvement and can make the change yourself go
19 | ahead and use a typical git workflow to make it happen:
20 |
21 | * Fork this curriculum repository
22 | * Make the change on your fork, with descriptive commits in the standard format
23 | * Open a Pull Request against this repo
24 |
25 | A curriculum owner will review your change and approve or comment on it in due
26 | course.
27 |
28 | # Why Contribute?
29 |
30 | Curriculum on Learn is publicly and freely available under Learn's
31 | [Educational Content License](https://learn.co/content-license). By
32 | embracing an open-source contribution model, our goal is for the curriculum
33 | on Learn to become, in time, the best educational content the world has
34 | ever seen.
35 |
36 | We need help from the community of Learners to maintain and improve the
37 | educational content. Everything from fixing typos, to correcting
38 | out-dated information, to improving exposition, to adding better examples,
39 | to fixing tests—all contributions to making the curriculum more effective are
40 | welcome.
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A React App Example
2 |
3 | ## Learning Goals
4 |
5 | - Understand the folder structure and key files for running a React application
6 | - Explore the structure of a basic React component
7 | - Debug React components using the React Developer Tools
8 |
9 | ## Introduction
10 |
11 | Before we dive in and start working on specific parts of a React project, let's
12 | take a look at a simple React application so we can understand it at a high
13 | level.
14 |
15 | In this lesson, we will start with a basic React app, examine the default
16 | directory structure, and gain a better understanding of how these apps are
17 | built.
18 |
19 | ## Starting Up a React App
20 |
21 | This lesson has all the necessary parts of a fully working React app. First,
22 | make sure you're running a compatible version of Node. You should be using Node
23 | 16, since Node 17 has some compatibility issues with several JavaScript
24 | libraries. To check your Node version, run the following, and verify that Node
25 | 16.x.x is installed and is the default version (the -> indicates the default):
26 |
27 | ```console
28 | $ nvm list
29 |
30 | -> v16.13.0
31 | v17.0.1
32 | system
33 | default -> 16 (-> v16.13.0)
34 | ```
35 |
36 | If it's not, you can install it and set it as the default with the following
37 | commands:
38 |
39 | ```console
40 | $ nvm install 16
41 | $ nvm alias default 16
42 | $ nvm use 16
43 | ```
44 |
45 | Next, make sure to download the source code for this lesson. Use the "Fork" link
46 | at the top of the page to fork and clone this lesson onto your computer. Then
47 | navigate into the lesson's directory and run:
48 |
49 | ```console
50 | $ npm install
51 | ```
52 |
53 | This will get and install all the required dependencies for React.
54 |
55 | Next, we need to start up a server for the app to run on:
56 |
57 | ```console
58 | $ npm start
59 | ```
60 |
61 | This will host the app and open a browser window to display it. If the server
62 | started correctly but the browser doesn't open, you can use the links that
63 | appear in the terminal to access the app. They should look something like this:
64 |
65 | ```console
66 | Local: http://localhost:3000
67 | On Your Network: http://192.168.1.5:3000
68 | ```
69 |
70 | You can use the `Local` link to open the app in your own browser. The second is
71 | for any _other_ computers on your network that you want to access your app from
72 | (this is particularly useful if you want to test out your app in a mobile
73 | browser on your phone).
74 |
75 | If everything has worked correctly, you should see a page with the exact time it
76 | was loaded, along with a small amount of text and a GIF.
77 |
78 | If we make any changes to our app while the server is running, it will 'hot
79 | reload,' and update the app in the browser. If there are app-breaking errors in
80 | your code, the browser will display those errors instead.
81 |
82 | We'll start by exploring the JavaScript code for this sample app in the `src`
83 | directory.
84 |
85 | ## index.js
86 |
87 | The "entry point" into our application — the first JavaScript code that will run
88 | when our app starts up — is in the `src/index.js` file. Open that file in your
89 | text editor. Inside, you'll see something like this:
90 |
91 | ```jsx
92 | import React from "react";
93 | import ReactDOM from "react-dom";
94 | import App from "./components/App";
95 | import "./index.css";
96 |
97 | ReactDOM.render(, document.getElementById("root"));
98 | ```
99 |
100 | We'll talk about the `import` statements in a bit, but for now, let's have a
101 | look at `ReactDOM.render()`.
102 |
103 | This `render` method comes from the `react-dom` package. It takes in two
104 | arguments:
105 |
106 | - A **React component** to render (typically, we'll render our top-level `App`
107 | component here).
108 | - A **DOM element** where we want that component to be rendered (by convention,
109 | a `div` with the ID of `root`).
110 |
111 | `ReactDOM.render()` will always be used in your applications. This one small
112 | function is how the rest of our application — all the components we'll write —
113 | will eventually make its way onto the DOM!
114 |
115 | Even though React is a modern, complex framework, it still relies on a regular
116 | `index.html` file to load the JavaScript! The file can be found in the `public`
117 | folder. Take a look at it now. Can you see where the `div` with the ID of `root`
118 | is?
119 |
120 | In general, when you're given a React project to work with, it's a good idea to
121 | start by reading the `index.js` file then work your way down from there into the
122 | rest of the components.
123 |
124 | ## App.js
125 |
126 | Next, open up `src/components/App.js` in a text editor. This file contains our
127 | `App` component. Within the `App` component is a section of code that looks
128 | _very much_ like HTML:
129 |
130 | ```jsx
131 |
132 |
{format(new Date(), "MMMM do yyyy, h:mm:ss a")}
133 |
134 | In React apps, we write JSX - it looks like HTML, and uses a lot of HTML
135 | syntax. JSX lets us include JavaScript functions right along with the HTML,
136 | and also allows us to add in components, which are separate, self-contained
137 | chunks of JSX.
138 |
139 |
140 |
141 | ```
142 |
143 | There's also some _JavaScript_ code mixed in with this HTML-like syntax:
144 |
145 | ```js
146 | format(new Date(), "MMMM do yyyy, h:mm:ss a");
147 | ```
148 |
149 | As it turns out, this is actually _all_ JavaScript. The HTML-like syntax is
150 | called JSX. It lets us write code that looks nearly identical to HTML, but
151 | allows us to mix in vanilla JavaScript and other neat things.
152 |
153 | Reading through the JSX code, we've got one `div` that contains three child
154 | elements, `
`, `
` and ``. In your browser, _these_ are
155 | the elements being displayed! The `
` provides a timestamp of the exact time
156 | the app was loaded, and the `
` section includes the brief text on JSX.
157 |
158 | The `ExampleComponent` contains the sunglasses GIF. In the `src` folder, take a
159 | look at `ExampleComponent.js`. You'll see a file very similar to `App.js`,
160 | containing `` and `
` elements.
161 |
162 | By including `` in `App.js`'s JSX, we are able to use the
163 | contents of the component. If you copy and paste `` so it is
164 | listed two times in a row, _two_ GIFs will appear on the page. Try this now.
165 |
166 | What about the rest of `App.js`, though? Moving out from the middle, we see this
167 | JSX code is the _return_ value of a function called `App`:
168 |
169 | ```js
170 | function App() {
171 |
172 | return (
173 | // JSX goes here!
174 | )
175 | }
176 | ```
177 |
178 | The key thing to understand is that all of the _visible content_ of our app is
179 | returned from this `App` function.
180 |
181 | We've already seen that it is possible to have multiple files that contain
182 | visible content, i.e., by using both `App` and `ExampleComponent`.
183 | `ExampleComponent`, however, is used within `App`. `App` is at the top-most
184 | level; it is the _parent component_ of our React app content.
185 |
186 | ## Importing, Exporting, and the Dependency Tree
187 |
188 | There are two other sections in the `App.js` file we haven't touched on: the
189 | `import` and `export` sections at the top and bottom.
190 |
191 | ```js
192 | import React from "react";
193 | import { format } from "date-fns";
194 | import ExampleComponent from "./ExampleComponent";
195 |
196 | function App() {
197 | // etc
198 | }
199 |
200 | export default App;
201 | ```
202 |
203 | `react` and `date-fns` are both npm packages, so what is happening here?
204 | `App.js` is _pulling in_ specific content from these two packages! `react` and
205 | `date-fns` are being _imported_ from the `node_modules` folder, which was
206 | created when we ran `npm install`.
207 |
208 | You can see in the `App` function that `format` from the `date-fns` library is
209 | being used in the return statement when we call `format(...)`.
210 |
211 | `react` is also being used, even though you can't see it written in the code!
212 | Anywhere you write JSX inside a component, it is actually _transpiled_ to
213 | JavaScript code that looks like this:
214 | `React.createElement(tagName, props, children)` (more on that later).
215 |
216 | > Version 17 of React, released October 2020, introduced a new JSX
217 | > transformation. So instead of `React.createElement()`, the JSX is transpiled
218 | > into `_jsx()`. You can read more about the change [here][jsx].
219 | >
220 | > With React 17, you can actually _omit_ the line `import React from "react"` in
221 | > your component files, and they'll still work just fine. You can find out which
222 | > version of React a project is using by looking at `dependencies` section of
223 | > the `package.json` file. Our lessons typically use React 17 and above, so
224 | > you'll often see the import statement for React has been omitted.
225 |
226 | The import for `ExampleComponent` is slightly different. Rather than importing
227 | code from a package, here we are importing something from within our project's
228 | file tree. By importing `./ExampleComponent`, we make ``
229 | available for use in the `App` component's return statement.
230 |
231 | OK, then what is happening with `export`? By including the `export` line, we are
232 | allowing _other_ files to _import_ things from the `App.js` file. There are
233 | different types of exports, like named exports and default exports, but we will
234 | dive deeper into this topic in a later lesson.
235 |
236 | For now, we will just focus on default exports. The line, `export default App`
237 | denotes that our `App` function is the main thing we want to export from our
238 | `App.js` file. You can have only one default export per file. If you take a look
239 | at `index.js`, you can see at the top of the file that we are _importing_ `App`
240 | from the `App.js` file in the `src/components` directory (the `.js` does not
241 | need to be included). This import statement is what we use to import something
242 | that is the default export of another file:
243 |
244 | ```js
245 | import App from "./components/App";
246 | ```
247 |
248 | This structure of importing and exporting allows for files to create a 'tree' of
249 | dependencies. `ExampleComponent.js` has an `export` statement as well (take the
250 | time to locate it), and is imported into `App.js`. Additionally, `App.js` is
251 | imported into `index.js`.
252 |
253 | The `index.js` file doesn't have an export. It is the 'top' of this dependency
254 | tree.
255 |
256 | ## Debugging Components
257 |
258 | React has a great set of developer tools that make it easier to view our
259 | components in the browser and debug what's happening under the hood. Install the
260 | React Developer Tools [Chrome Extension][devtools-chrome] or [Firefox
261 | Extension][devtools-firefox]. Here is the [readme][devtools-readme] for the
262 | extension.
263 |
264 | After installing, restart your browser, then go to `http://localhost:3000` to
265 | view our React application. Open your browser's developer tools, and find the
266 | **Components** tab. Here, you'll see the component hierarchy with information
267 | about all the components we're using so far in the app!
268 |
269 | 
270 |
271 | ## Deliverables
272 |
273 | There are three tests to pass in this lesson. They are all related to the
274 | content within `src/components/App.js`.
275 |
276 | 1. Replace the contents of the `h1` element so that, instead of a time, it just
277 | says 'Now'
278 | 2. If you added a second ``, be sure to remove it
279 | 3. Add in a _new_ component, ``, just below
280 | ``, in the `App.js` file (remember: you will need to
281 | **import** the component before you can use it)
282 |
283 | When working on React labs, it's helpful to have two terminal tabs open:
284 |
285 | - In the first tab, run `npm start` to run your React app in the browser
286 | - In the second tab, run `learn test` or `npm test` to see the test output
287 |
288 | ## Conclusion
289 |
290 | There is a lot we still haven't touched on, and we will go into greater depth on
291 | how things work in the following lessons. Almost all of our work, however, will
292 | be done within `App.js` and child components of it. This is where all of our
293 | creative energy will be spent.
294 |
295 | This file structure in this lesson is what `create-react-app` automatically
296 | generates, and it's what you'll see in many React projects. Using this
297 | structure, a lot of set-up is abstracted away. We have all the boilerplate code
298 | in place in the `index.html` and `index.js` files so that we can start focusing
299 | on writing the core functionality of our app using components, like in `App.js`.
300 |
301 | ## Resources
302 |
303 | - [React DevTools - Chrome][devtools-chrome]
304 | - [React DevTools - Firefox][devtools-firefox]
305 |
306 | [jsx]:
307 | https://reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html
308 | [devtools-chrome]:
309 | https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en
310 | [devtools-firefox]:
311 | https://addons.mozilla.org/en-US/firefox/addon/react-devtools/
312 | [devtools-readme]: https://www.npmjs.com/package/react-devtools
313 |
--------------------------------------------------------------------------------