├── .gitignore ├── 01-basic ├── Dockerfile ├── README.md ├── docker-compose.yml ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── aboutus.js │ ├── home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── navigation.js │ └── notfound.js ├── 02-params ├── README.md ├── __tests__ │ ├── App.contact.success.test.js │ ├── App.test.js │ ├── data.json │ ├── data │ │ └── index.js │ └── query,test.js ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── aboutus.js │ ├── application.js │ ├── contact.js │ ├── home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── navigation.js │ ├── notfound.js │ ├── posts.js │ └── queries.js ├── 03-nested ├── README.md ├── __tests__ │ ├── App.test.js │ └── data.json ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── aboutus.js │ ├── application.js │ ├── application │ └── notes │ │ └── noteService.js │ ├── contact.js │ ├── home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── navigation.js │ ├── note.js │ ├── notes.js │ └── notfound.js ├── 04-transitions ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── AppForm.js │ ├── aboutus.js │ ├── home.js │ ├── index.css │ ├── index.js │ └── logo.svg └── yarn.lock ├── 05-redux ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── AppForm.js │ ├── Navigation.js │ ├── home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ └── reducers │ └── register.js ├── 06-Prompt ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ └── logo.svg ├── 07-Navigation ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ └── redirector.js ├── 08-switch ├── .gitignore ├── README.md ├── package.json ├── public │ ├── favicon.ico │ └── index.html └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ └── navigation.js └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | node_modules 5 | 6 | # testing 7 | coverage 8 | 9 | # production 10 | build 11 | 12 | # misc 13 | .DS_Store 14 | .env 15 | npm-debug.log 16 | -------------------------------------------------------------------------------- /01-basic/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:6.3.1 2 | 3 | RUN mkdir -p /usr/src/app 4 | WORKDIR /usr/src/app 5 | COPY . /usr/src/app 6 | 7 | CMD npm start -------------------------------------------------------------------------------- /01-basic/README.md: -------------------------------------------------------------------------------- 1 | # Basic setup 2 | This project setups up a basic website with two pages within the route and a 3 | default page if the route is not found. 4 | 5 | ``` 6 | npm install 7 | npm start 8 | ``` 9 | 10 | ## Match 11 | This looks at the location and using a Regular Expression will show the 12 | associated component specified within the component Prop. 13 | 14 | ## Miss 15 | This is the component to display if the route didn't match. 16 | -------------------------------------------------------------------------------- /01-basic/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | services: 4 | app: 5 | build: 6 | context: . 7 | ports: 8 | - "3000:3000" 9 | volumes: 10 | - .:/usr/src/app -------------------------------------------------------------------------------- /01-basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "navigatingreactrouterbasics", 3 | "version": "0.0.1", 4 | "private": true, 5 | "devDependencies": { 6 | "react-scripts": "0.6.1" 7 | }, 8 | "dependencies": { 9 | "react": "^15.3.2", 10 | "react-dom": "^15.3.2", 11 | "react-router": "^4.0.0-beta.7", 12 | "react-router-dom": "^4.0.0-beta.7" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test --env=jsdom", 18 | "eject": "react-scripts eject" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /01-basic/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gpltaylor/react-router-workshop/19d1437833dfc7d806c8e54a3a8f7db756a7311a/01-basic/public/favicon.ico -------------------------------------------------------------------------------- /01-basic/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | React App 17 | 18 | 19 |
20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /01-basic/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-intro { 18 | font-size: large; 19 | } 20 | 21 | @keyframes App-logo-spin { 22 | from { transform: rotate(0deg); } 23 | to { transform: rotate(360deg); } 24 | } 25 | -------------------------------------------------------------------------------- /01-basic/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | import { 6 | BrowserRouter as Router, 7 | Route, 8 | Switch 9 | } from 'react-router-dom'; 10 | 11 | import Navigation from './navigation'; 12 | import Home from './home'; 13 | import About from './aboutus'; 14 | import NotFound from './notfound'; 15 | 16 | var App = () => { 17 | return ( 18 | 19 |
20 |
21 | logo 22 |

Good bye crual world

23 |
24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 | ) 35 | } 36 | 37 | export default App; 38 | -------------------------------------------------------------------------------- /01-basic/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /01-basic/src/aboutus.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | var About = () => { 4 | return
5 |

About Us

6 |

A little bit about us

7 |
8 | } 9 | 10 | export default About; 11 | -------------------------------------------------------------------------------- /01-basic/src/home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | var Home = () => { 4 | return
5 |

Home

6 |

Welcome to the best React Router Tutorial you will EVER see!!!! yeahhhh baby

7 |
8 | } 9 | 10 | export default Home; 11 | -------------------------------------------------------------------------------- /01-basic/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: sans-serif; 5 | } 6 | 7 | ul li { 8 | list-style-type: none; 9 | display: inline; 10 | } 11 | 12 | li+li:before 13 | { 14 | content: ' | '; 15 | } 16 | -------------------------------------------------------------------------------- /01-basic/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import App from './App'; 5 | 6 | import './index.css'; 7 | 8 | ReactDOM.render( 9 | , 10 | document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /01-basic/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /01-basic/src/navigation.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Link from 'react-router-dom/Link'; 3 | 4 | var Navigation = () => { 5 | return
6 |
    7 |
  • Home
  • 8 |
  • About
  • 9 |
  • Missing
  • 10 |
11 |
12 | } 13 | 14 | export default Navigation; 15 | -------------------------------------------------------------------------------- /01-basic/src/notfound.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | var NotFound = ({location}) => { 4 | return
5 |

Not Found

6 |

Sorry but the page {location.pathname}, can not be found.

7 |
8 | } 9 | 10 | export default NotFound; 11 | -------------------------------------------------------------------------------- /02-params/README.md: -------------------------------------------------------------------------------- 1 | # Parameters 2 | Demonstrates how to use React-Router parameters. 3 | 4 | ``` 5 | npm install 6 | npm start 7 | ``` 8 | 9 | ## :id 10 | A Splat allows you to grab a section of the URL and pass into your Component 11 | as a Prop. 12 | 13 | ``` 14 | http://localhost:8080/post/:name 15 | /posts/:name 16 | ``` 17 | Load a website blog post with a given name. This will get the name from the 18 | given part of the URL and pass in as props to the assigned Component. 19 | 20 | ``` 21 | http://localhost:8080/Application/TAY215485/notes/232 22 | /application/:appId/notes/:noteid 23 | ``` 24 | In this example you can see that you can use as many splats as required. 25 | Here we are loading an application (TAY215485) and getting a note (232). 26 | 27 | This would allow you to make a call to an API to return details about the 28 | application and the given note, displaying the results within the selected 29 | component. 30 | -------------------------------------------------------------------------------- /02-params/__tests__/App.contact.success.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from '../src/App'; 4 | 5 | import Router from 'react-router/MemoryRouter'; 6 | import { renderToString, renderToStaticMarkup } from 'react-dom/server'; 7 | 8 | import { 9 | homeHTML, aboutHTML, applicationHTML, applicationWithNotesHTML, 10 | missingHTML, contactHTML, contactSuccessHTML, empty 11 | } from "./data/index"; 12 | 13 | describe('app.contact.test', () => { 14 | it('Successfully completed', () => { 15 | const div = document.createElement('div'); 16 | const pathname = '/contact'; 17 | const query = { 18 | firstName: "Garry", 19 | message: "Thank you for watching the best react-router demo ever!" 20 | } 21 | 22 | const html = renderToStaticMarkup( 23 | 24 | ); 25 | 26 | expect(html).toContain(contactSuccessHTML); 27 | }); 28 | 29 | it('Show contact form', () => { 30 | const div = document.createElement('div'); 31 | const pathname = '/contact'; 32 | const html = renderToStaticMarkup( 33 | 34 | ); 35 | 36 | expect(html).toContain(contactHTML); 37 | }); 38 | 39 | }); -------------------------------------------------------------------------------- /02-params/__tests__/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from '../src/App'; 4 | 5 | import Router from 'react-router/MemoryRouter'; 6 | import { renderToString, renderToStaticMarkup } from 'react-dom/server'; 7 | 8 | import { 9 | homeHTML, aboutHTML, applicationHTML, applicationWithNotesHTML, 10 | missingHTML, contactHTML, contactSuccessHTML, empty 11 | } from "./data/index"; 12 | 13 | describe('app.test', () => { 14 | 15 | it('App renders correctly', () => { 16 | const div = document.createElement('div'); 17 | const pathname = '/about'; 18 | const html = renderToStaticMarkup( 19 | 20 | ); 21 | 22 | expect(html).toContain(aboutHTML); 23 | }); 24 | 25 | it('Application has appId props and notes has noteId', () => { 26 | const div = document.createElement('div'); 27 | const pathname = '/application/ALF-34059/notes/987654'; 28 | const html = renderToStaticMarkup( 29 | 30 | ); 31 | 32 | expect(html).toContain(applicationWithNotesHTML); 33 | }); 34 | 35 | }); -------------------------------------------------------------------------------- /02-params/__tests__/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "/": "test", 3 | "/queries": "

Links

" 4 | } -------------------------------------------------------------------------------- /02-params/__tests__/data/index.js: -------------------------------------------------------------------------------- 1 | export const applicationHTML = "

Application

Application : ALF-34059

Notes :

" 2 | 3 | export const applicationWithNotesHTML = "

Application

Application : ALF-34059

Notes : 987654

" 4 | 5 | export const homeHTML = "

Homes

Welcome to the best React Router Tutorial you will EVER see!!!! yeahhhh baby

" 6 | 7 | export const aboutHTML = "

About Us

A little bit about us

" 8 | 9 | export const missingHTML = "

Not Found

" 10 | 11 | export const contactHTML = "

Contact

Please complete the following form

" 12 | 13 | export const contactSuccessHTML = "

Thank you, Garry!

Thank you for watching the best react-router demo ever!

Your message shown above has been successfully submitted. We will be in contact with your shortly.

" 14 | 15 | export const empty = "
" 16 | 17 | it('test data to be defined', () => { 18 | expect(true).toBe(true); 19 | }) -------------------------------------------------------------------------------- /02-params/__tests__/query,test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from '../src/App'; 4 | 5 | import Router from 'react-router/MemoryRouter'; 6 | import { renderToString, renderToStaticMarkup } from 'react-dom/server'; 7 | 8 | import data from "./data.json"; 9 | 10 | describe("query.test.js", () => { 11 | it('App renders correctly', () => { 12 | const div = document.createElement('div'); 13 | 14 | const pathname = "/queries"; 15 | const html = renderToStaticMarkup( 16 | 17 | ); 18 | 19 | expect(html).toContain(data[pathname]); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /02-params/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "navigatingreactrouterparams", 3 | "version": "0.0.1", 4 | "private": true, 5 | "devDependencies": { 6 | "react-scripts": "0.6.1" 7 | }, 8 | "dependencies": { 9 | "react": "^15.3.2", 10 | "react-dom": "^15.3.2", 11 | "react-router": "^4.0.0-alpha.4" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "build": "react-scripts build", 16 | "test": "react-scripts test --env=jsdom", 17 | "eject": "react-scripts eject" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /02-params/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gpltaylor/react-router-workshop/19d1437833dfc7d806c8e54a3a8f7db756a7311a/02-params/public/favicon.ico -------------------------------------------------------------------------------- /02-params/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | React App 17 | 18 | 19 |
20 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /02-params/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 80px; 8 | } 9 | 10 | .App-header { 11 | background-color: #222; 12 | height: 150px; 13 | padding: 20px; 14 | color: white; 15 | } 16 | 17 | .App-intro { 18 | font-size: large; 19 | } 20 | 21 | @keyframes App-logo-spin { 22 | from { transform: rotate(0deg); } 23 | to { transform: rotate(360deg); } 24 | } 25 | -------------------------------------------------------------------------------- /02-params/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | import {Match, Miss} from 'react-router' 5 | 6 | import Navigation from './navigation'; 7 | import Home from './home'; 8 | import About from './aboutus'; 9 | import NotFound from './notfound'; 10 | import Posts from './posts'; 11 | import Application from './application'; 12 | import Contact from './contact'; 13 | import Queries from './queries'; 14 | 15 | var App = () => { 16 | return ( 17 |
18 |
19 | logo 20 |

Welcome to React

21 |
22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 | ) 34 | } 35 | 36 | export default App; 37 | -------------------------------------------------------------------------------- /02-params/src/aboutus.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | var About = () => { 4 | return
5 |

About Us

6 |

A little bit about us

7 |
8 | } 9 | 10 | export default About; 11 | -------------------------------------------------------------------------------- /02-params/src/application.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | var application = ({params}) => { 4 | return
5 |

Application

6 |

Application : {params.appId}

7 |

Notes : {params.noteId}

8 |
9 | } 10 | 11 | export default application; 12 | -------------------------------------------------------------------------------- /02-params/src/contact.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | var Contact = ({location}) => { 4 | 5 | return
6 | {location.query == null ? 7 |
8 |

Contact

9 |

Please complete the following form

10 |
11 | 12 | 13 |