├── .all-contributorsrc ├── .gitignore ├── README.md ├── _params.yaml ├── code ├── 10 │ ├── content-search.js │ ├── header-click.js │ ├── header-no-click.js │ ├── header-search.js │ ├── interactionBindings.js │ ├── mousemove.js │ ├── search-form.js │ └── working-search.js ├── 01 │ └── .keep ├── 03 │ └── app1.html ├── 04 │ ├── container.jsx │ ├── container2.jsx │ ├── content1.jsx │ ├── header.jsx │ └── timeline1.jsx ├── 05 │ ├── activity_item.jsx │ ├── content1.jsx │ ├── content2.jsx │ ├── content3.jsx │ ├── content4.jsx │ ├── header1.jsx │ └── header2.jsx ├── 06 │ ├── header1.js │ └── timer1.jsx ├── 07 │ ├── container1.js │ ├── content1.js │ ├── content2.js │ └── timer1.js ├── 08 │ ├── basic-proptypes.js │ ├── collection-proptypes.js │ ├── element-proptypes.js │ ├── object-proptypes.js │ └── proptypes1.js └── 09 │ ├── header1.js │ └── inline-header.js ├── day-01 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ └── index.html ├── day-02 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ └── index.html ├── day-03 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ ├── app.html │ └── app2.html ├── day-04 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ ├── Timeline.css │ ├── app1.html │ ├── app2.html │ └── assets │ └── images │ ├── breakdown-2.jpg │ ├── breakdown-2.png │ ├── breakdown.jpg │ ├── breakdown.png │ └── part4.sketch ├── day-05 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ ├── content.html │ ├── content2.html │ ├── content3.html │ ├── header.html │ ├── header2.html │ └── header3.html ├── day-06 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ ├── Clock.css │ ├── clock-state.html │ └── clock.html ├── day-07 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ ├── clock.html │ ├── container.html │ ├── content.html │ └── data.js ├── day-08 ├── BasicProptypes.js ├── CollectionProptypes.js ├── ElementProptypes.js ├── ObjectProptypes.js ├── Proptypes1.js ├── UserLink.js ├── cover.jpg ├── doc │ └── doc.mkd └── post.md ├── day-09 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ ├── header-inline.html │ ├── header.html │ ├── styles.css │ └── text-color.html ├── day-10 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ ├── header-click.html │ ├── header-search-form-onchange.html │ ├── header-search-form.html │ ├── interaction-event-bindings.html │ ├── mouse-move-react.html │ ├── mouse-move.html │ ├── search.html │ └── styles.css ├── day-11 ├── cover.jpg ├── doc │ └── doc.mkd ├── post.md └── public │ └── clock.html ├── day-12 ├── .gitignore ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── components │ │ ├── Content.js │ │ └── Header.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-13 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── components │ │ ├── Repeater.js │ │ ├── ShowA.js │ │ └── Timer │ │ │ ├── Ampm.js │ │ │ ├── CleanerFormatter.js │ │ │ ├── Clock.js │ │ │ ├── Formatter.js │ │ │ ├── Hour.js │ │ │ ├── Minute.js │ │ │ ├── Second.js │ │ │ └── Separator.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-14 ├── cover.jpg ├── doc │ └── doc.mkd └── post.md ├── day-15 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── getCurrentTimeCallback.js │ ├── getCurrentTimeHandlerId.js │ ├── getCurrentTimeOnFail.js │ ├── getCurrentTimePromise.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-16 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── TimeForm.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-17 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── SimpleRouter.js │ ├── TwoLinkedRoutes.js │ ├── TwoLinkedSingleRenderedRoutes.js │ ├── TwoLinkedSingleRoutes.js │ ├── TwoRoutes.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-18 ├── cover.jpg ├── doc │ └── doc.mkd └── post.md ├── day-19 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.test.js │ ├── containers │ │ ├── App.js │ │ ├── Root.js │ │ └── views │ │ │ ├── About │ │ │ └── About.js │ │ │ └── Home │ │ │ └── Home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── redux │ │ ├── configureStore.js │ │ ├── reducers.js │ │ └── types.js │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-20 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.test.js │ ├── containers │ │ ├── App.js │ │ ├── Root.js │ │ └── views │ │ │ ├── About │ │ │ └── About.js │ │ │ └── Home │ │ │ └── Home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── redux │ │ ├── actionCreators.js │ │ ├── configureStore.js │ │ ├── currentUser.js │ │ ├── reducers.js │ │ └── types.js │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-21 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.css │ ├── App.test.js │ ├── containers │ │ ├── App.js │ │ ├── Root.js │ │ └── views │ │ │ ├── About │ │ │ └── About.js │ │ │ └── Home │ │ │ └── Home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── redux │ │ ├── actionCreators.js │ │ ├── apiMiddleware.js │ │ ├── configureStore.js │ │ ├── currentTime.js │ │ ├── currentUser.js │ │ ├── loggingMiddleware.js │ │ ├── reducers.js │ │ └── types.js │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-22 ├── cover.jpg ├── doc │ └── doc.mkd └── post.md ├── day-23 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── components │ │ └── Timeline │ │ │ ├── Timeline.css │ │ │ ├── Timeline.js │ │ │ └── __tests__ │ │ │ └── Timeline-test.js │ ├── index.js │ └── logo.svg └── yarn.lock ├── day-24 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── components │ │ └── Timeline │ │ │ ├── Timeline.css │ │ │ ├── Timeline.js │ │ │ └── __tests__ │ │ │ └── Timeline-test.js │ ├── index.js │ └── logo.svg └── yarn.lock ├── day-25 ├── README.md ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── components │ │ └── Timeline │ │ │ ├── ActivityItem.js │ │ │ ├── Header.js │ │ │ ├── Timeline.css │ │ │ ├── Timeline.js │ │ │ └── __tests__ │ │ │ ├── Timeline-test-test-utils.js │ │ │ └── Timeline-test.js │ ├── data.json │ ├── index.js │ ├── logo.svg │ └── setupTests.js └── yarn.lock ├── day-26 ├── cover.jpg ├── doc │ └── doc.mkd ├── nightwatch.json ├── package.json ├── post.md ├── public │ ├── favicon.ico │ └── index.html ├── reports │ ├── CHROME_57.0.2987.133_MAC_auth-flow.xml │ └── CHROME_79.0.3945.79_Linux_auth-flow.xml ├── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── Root.js │ ├── components │ │ ├── Form │ │ │ ├── Form.js │ │ │ └── Input.js │ │ └── Nav │ │ │ └── Navbar.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── redux │ │ ├── actions │ │ │ └── auth.js │ │ ├── configureStore.js │ │ ├── reducers │ │ │ ├── auth.js │ │ │ └── index.js │ │ └── types.js │ ├── styles │ │ └── index.css │ └── views │ │ ├── About.js │ │ ├── Home.js │ │ └── Login.js ├── tests │ └── auth-flow.js └── yarn.lock ├── day-27 ├── config │ ├── development.config.env │ ├── env.js │ ├── jest │ │ ├── cssTransform.js │ │ └── fileTransform.js │ ├── modules.js │ ├── paths.js │ ├── pnpTs.js │ ├── production.config.env │ ├── webpack.config.js │ └── webpackDevServer.config.js ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── scripts │ ├── build.js │ ├── start.js │ └── test.js ├── src │ ├── App.css │ ├── App.test.js │ ├── containers │ │ ├── App.js │ │ ├── Root.js │ │ └── views │ │ │ ├── About │ │ │ └── About.js │ │ │ └── Home │ │ │ └── Home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── redux │ │ ├── actionCreators.js │ │ ├── apiMiddleware.js │ │ ├── configureStore.js │ │ ├── currentTime.js │ │ ├── currentUser.js │ │ ├── loggingMiddleware.js │ │ ├── reducers.js │ │ └── types.js │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-28 ├── cover.jpg ├── doc │ └── doc.mkd └── post.md ├── day-29 ├── .travis.yml ├── config │ ├── development.config.env │ ├── env.js │ ├── jest │ │ ├── cssTransform.js │ │ └── fileTransform.js │ ├── modules.js │ ├── paths.js │ ├── pnpTs.js │ ├── production.config.env │ ├── webpack.config.js │ └── webpackDevServer.config.js ├── cover.jpg ├── doc │ └── doc.mkd ├── package.json ├── post.md ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── scripts │ ├── build.js │ ├── deploy.sh │ ├── release.js │ ├── start.js │ └── test.js ├── src │ ├── App.css │ ├── App.test.js │ ├── containers │ │ ├── App.js │ │ ├── Root.js │ │ └── views │ │ │ ├── About │ │ │ └── About.js │ │ │ └── Home │ │ │ └── Home.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── redux │ │ ├── actionCreators.js │ │ ├── apiMiddleware.js │ │ ├── configureStore.js │ │ ├── currentTime.js │ │ ├── currentUser.js │ │ ├── loggingMiddleware.js │ │ ├── reducers.js │ │ └── types.js │ ├── serviceWorker.js │ └── setupTests.js └── yarn.lock ├── day-30 ├── cover.jpg ├── doc │ └── doc.mkd └── post.md ├── images ├── 12 │ ├── app.jpg │ ├── app.png │ ├── build.jpg │ ├── build.png │ ├── chrome-start.jpg │ ├── chrome-start.png │ ├── create-app.jpg │ ├── create-app.png │ ├── index-html.jpg │ ├── index-html.png │ ├── install-create-react-app.jpg │ ├── install-create-react-app.png │ ├── npm-start.jpg │ ├── npm-start.png │ ├── tree.jpg │ └── tree.png ├── 13 │ ├── children-map.jpg │ ├── children-map.png │ ├── run-no-key.jpg │ └── run-no-key.png ├── 14 │ ├── install-fetch.jpg │ └── install-fetch.png ├── 17 │ ├── install-react-router.jpg │ └── install-react-router.png ├── 19 │ ├── home-time.jpg │ ├── home-time.png │ ├── install-redux.jpg │ ├── install-redux.png │ ├── no-reducer.jpg │ ├── no-reducer.png │ ├── structure.jpg │ └── structure.png ├── 20 │ ├── home-time.jpg │ ├── home-time.png │ └── login-logout.gif ├── 23 │ ├── first-tests.jpg │ ├── first-tests.png │ ├── second-tests.jpg │ └── second-tests.png ├── 24 │ ├── failing-test-1.jpg │ ├── failing-test-1.png │ ├── failing-test-2.jpg │ ├── failing-test-2.png │ ├── navbar.jpg │ ├── navbar.png │ ├── passing-test-1.jpg │ ├── passing-test-1.png │ └── passing-test.png ├── 25 │ ├── enzyme-test-1.jpg │ ├── enzyme-test-1.png │ ├── enzyme-test-2.jpg │ ├── enzyme-test-2.png │ ├── enzyme-test-3.jpg │ └── enzyme-test-3.png ├── 26 │ ├── nightwatch-1.jpg │ ├── nightwatch-1.png │ ├── nightwatch-2.jpg │ ├── nightwatch-2.png │ ├── nightwatch-3.jpg │ ├── nightwatch-3.png │ ├── npm-start.jpg │ ├── npm-start.png │ ├── selenium-server.jpg │ └── selenium-server.png ├── 28 │ ├── bitballoon.jpg │ ├── bitballoon.png │ ├── gh-pages.jpg │ ├── gh-pages.png │ ├── git-branch.jpg │ ├── git-branch.png │ ├── github-pages.jpg │ ├── github-pages.png │ ├── github-repo.jpg │ ├── github-repo.png │ ├── github-url.jpg │ ├── github-url.png │ ├── heroku-create.jpg │ ├── heroku-create.png │ ├── heroku-deploy.jpg │ ├── heroku-deploy.png │ ├── heroku-login.jpg │ ├── heroku-login.png │ ├── heroku-plugin.jpg │ ├── heroku-plugin.png │ ├── heroku-static-init.jpg │ ├── heroku-static-init.png │ ├── heroku.jpg │ ├── heroku.png │ ├── npm-build.jpg │ ├── npm-build.png │ ├── pancake.jpg │ ├── pancake.png │ ├── s3.jpg │ ├── s3.png │ ├── surge-deploy.jpg │ ├── surge-deploy.png │ ├── surge.jpg │ └── surge.png ├── 29 │ ├── deploy-fail.jpg │ ├── deploy-fail.png │ ├── deploy-script.jpg │ ├── deploy-script.png │ ├── travis-activate-repo.jpg │ ├── travis-activate-repo.png │ ├── travis-output.jpg │ ├── travis-output.png │ ├── travis-select-repo.jpg │ ├── travis-select-repo.png │ ├── travis-setup.jpg │ └── travis-setup.png ├── 04 │ ├── breakdown-2.jpg │ ├── breakdown-2.png │ ├── breakdown.jpg │ ├── breakdown.png │ └── part4.sketch ├── headings │ ├── 1.jpg │ ├── 10.jpg │ ├── 10_wide.jpg │ ├── 11.jpg │ ├── 11_wide.jpg │ ├── 12.jpg │ ├── 12_wide.jpg │ ├── 13.jpg │ ├── 13_wide.jpg │ ├── 14.jpg │ ├── 14_wide.jpg │ ├── 15.jpg │ ├── 15_wide.jpg │ ├── 16.jpg │ ├── 16_wide.jpg │ ├── 17.jpg │ ├── 17_wide.jpg │ ├── 18.jpg │ ├── 18_wide.jpg │ ├── 19.jpg │ ├── 19_wide.jpg │ ├── 1_wide.jpg │ ├── 2.jpg │ ├── 20.jpg │ ├── 20_wide.jpg │ ├── 21.jpg │ ├── 21_wide.jpg │ ├── 22.jpg │ ├── 22_wide.jpg │ ├── 23.jpg │ ├── 23_wide.jpg │ ├── 24.jpg │ ├── 24_wide.jpg │ ├── 25.jpg │ ├── 25_wide.jpg │ ├── 26.jpg │ ├── 26_wide.jpg │ ├── 27.jpg │ ├── 27_wide.jpg │ ├── 28.jpg │ ├── 28_wide.jpg │ ├── 29.jpg │ ├── 29_wide.jpg │ ├── 2_wide.jpg │ ├── 3.jpg │ ├── 30.jpg │ ├── 30_wide.jpg │ ├── 3_wide.jpg │ ├── 4.jpg │ ├── 4_wide.jpg │ ├── 5.jpg │ ├── 5_wide.jpg │ ├── 6.jpg │ ├── 6_wide.jpg │ ├── 7.jpg │ ├── 7_wide.jpg │ ├── 8.jpg │ ├── 8_wide.jpg │ ├── 9.jpg │ └── 9_wide.jpg └── readme │ ├── 30-days-of-react-book-cover-2-as-book-220.png │ ├── download-the-pdf-button.png │ └── fullstack-react-hero-book.png ├── index.html ├── internal ├── package.json ├── readme-chapters.js └── yarn.lock └── styles.css /_params.yaml: -------------------------------------------------------------------------------- 1 | note: 'This file is for fullstackreact.com internal use' 2 | series: 30-days-of-react 3 | isPrinting: false 4 | published: false 5 | draft: false 6 | author: auser 7 | autotoc: true 8 | fileMetaKeyHeadingsAllowed: true 9 | containerintro: 'partials/series/30-days-of-react/what-is-this.html' 10 | containerfooter: 'partials/series/30-days-of-react/postcontents.html' 11 | bodyClasses: thirty-days landingpage 12 | editOnGithubUrl: __GITHUB_REPO__/blob/master/day-__DAY_DIR__/post.md 13 | githubRepo: https://github.com/fullstackreact/30-days-of-react 14 | articleEntry: '30-days-of-react/__PERMALINK__-code/index' 15 | codeRoot: '__FILE_PATH__/code/__DAY_DIR__' 16 | imagesDir: '../../../assets/images/series/30-days-of-react/__DAY_DIR__' 17 | githubRepo: 'https://github.com/fullstackreact/30-days-of-react' 18 | variables: 19 | __DAY_DIR__: dayDir 20 | __GITHUB_REPO__: githubRepo 21 | __PERMALINK__: permalink 22 | -------------------------------------------------------------------------------- /code/01/.keep: -------------------------------------------------------------------------------- 1 | .keep -------------------------------------------------------------------------------- /code/03/app1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello world 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /code/04/container.jsx: -------------------------------------------------------------------------------- 1 | class App extends React.Component { 2 | render() { 3 | return ( 4 |
5 |
6 | {/* content goes here */} 7 |
8 |
9 | ) 10 | } 11 | } -------------------------------------------------------------------------------- /code/04/container2.jsx: -------------------------------------------------------------------------------- 1 | class App extends React.Component { 2 | render() { 3 | return ( 4 |
5 |
6 |
7 | 8 |
9 |
10 | ) 11 | } 12 | } -------------------------------------------------------------------------------- /code/04/content1.jsx: -------------------------------------------------------------------------------- 1 | class Content extends React.Component { 2 | render() { 3 | return ( 4 |
5 |
6 | 7 | {/* Timeline item */} 8 |
9 |
10 | 11 | Doug 12 |
13 | 14 | 15 | An hour ago 16 | 17 |

Ate lunch

18 |
19 | 2 20 |
21 |
22 | 23 | {/* ... */} 24 | 25 |
26 | ) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /code/04/header.jsx: -------------------------------------------------------------------------------- 1 | class Header extends React.Component { 2 | render() { 3 | return ( 4 |
5 |
6 | 7 | Timeline 8 | 9 | 13 | 14 |
15 |
16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /code/05/activity_item.jsx: -------------------------------------------------------------------------------- 1 | class ActivityItem extends React.Component { 2 | render() { 3 | const {activity} = this.props; // ES6 destructuring 4 | 5 | return ( 6 |
7 |
8 | 9 | {activity.user.name} 10 |
11 | 12 | 13 | {activity.timestamp} 14 | 15 |

{activity.text}

16 |
17 | {activity.comments.length} 18 |
19 |
20 | ) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /code/05/content1.jsx: -------------------------------------------------------------------------------- 1 | class Content extends React.Component { 2 | render() { 3 | return ( 4 |
5 |
6 | 7 | {/* Timeline item */} 8 |
9 |
10 | 11 | Doug 12 |
13 | 14 | 15 | An hour ago 16 | 17 |

Ate lunch

18 |
19 | 2 20 |
21 |
22 | 23 |
24 | ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /code/05/content2.jsx: -------------------------------------------------------------------------------- 1 | class Content extends React.Component { 2 | render() { 3 | const {activity} = this.props; // ES6 destructuring 4 | 5 | return ( 6 |
7 |
8 | 9 | {/* Timeline item */} 10 |
11 |
12 | 13 | {activity.user.name} 14 |
15 | 16 | 17 | {activity.timestamp} 18 | 19 |

{activity.text}

20 |
21 | {activity.comments.length} 22 |
23 |
24 |
25 | ) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /code/05/content3.jsx: -------------------------------------------------------------------------------- 1 | class Content extends React.Component { 2 | render() { 3 | const {activities} = this.props; // ES6 destructuring 4 | 5 | return ( 6 |
7 |
8 | 9 | {/* Timeline item */} 10 | {activities.map((activity) => { 11 | return ( 12 |
13 |
14 | 15 | {activity.user.name} 16 |
17 | 18 | 19 | {activity.timestamp} 20 | 21 |

{activity.text}

22 |
23 | {activity.comments.length} 24 |
25 |
26 | ); 27 | })} 28 | 29 |
30 | ) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /code/05/content4.jsx: -------------------------------------------------------------------------------- 1 | class Content extends React.Component { 2 | render() { 3 | const {activities} = this.props; // ES6 destructuring 4 | 5 | return ( 6 |
7 |
8 | 9 | {/* Timeline item */} 10 | {activities.map((activity) => ( 11 | 13 | ))} 14 | 15 |
16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /code/05/header1.jsx: -------------------------------------------------------------------------------- 1 | class Header extends React.Component { 2 | render() { 3 | return ( 4 |
5 |
6 | 7 | Timeline 8 | 9 | 13 | 14 |
15 |
16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /code/05/header2.jsx: -------------------------------------------------------------------------------- 1 | class Header extends React.Component { 2 | render() { 3 | return ( 4 |
5 |
6 | 7 | 8 | {this.props.title} 9 | 10 | 11 | 15 | 16 |
17 |
18 | ) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /code/07/container1.js: -------------------------------------------------------------------------------- 1 | class Container extends React.Component { 2 | constructor(props) { 3 | super(props); 4 | 5 | this.state = {refreshing: false} 6 | } 7 | 8 | // Bound to the refresh button 9 | refresh() { 10 | this.setState({refreshing: true}) 11 | } 12 | 13 | // Callback from the `Content` component 14 | onComponentRefresh() { 15 | this.setState({refreshing: false}); 16 | } 17 | 18 | render() { 19 | const {refreshing} = this.state; 20 | return ( 21 | 22 |
23 | {/* refreshing is the component's state */} 24 | 28 | {/* A container for styling */} 29 |
30 | 34 |
35 | 36 | ) 37 | } 38 | } -------------------------------------------------------------------------------- /code/07/content1.js: -------------------------------------------------------------------------------- 1 | class Content extends React.Component { 2 | render() { 3 | const {activities} = this.props; // ES6 destructuring 4 | 5 | return ( 6 |
7 |
8 | 9 | {/* Timeline item */} 10 | {activities.map((activity) => ( 11 | 13 | ))} 14 | 15 |
16 | ) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /code/07/timer1.js: -------------------------------------------------------------------------------- 1 | class Clock extends React.Component { 2 | constructor(props) { 3 | super(props); 4 | this.state = this.getTime(); 5 | } 6 | 7 | componentDidMount() { 8 | this.setTimer(); 9 | } 10 | 11 | setTimer() { 12 | this.timeout = setTimeout(this.updateClock.bind(this), 1000); 13 | } 14 | 15 | updateClock() { 16 | this.setState(this.getTime, this.setTimer); 17 | } 18 | 19 | getTime() { 20 | const currentTime = new Date(); 21 | return { 22 | hours: currentTime.getHours(), 23 | minutes: currentTime.getMinutes(), 24 | seconds: currentTime.getSeconds(), 25 | ampm: currentTime.getHours() >= 12 ? 'pm' : 'am' 26 | } 27 | } 28 | 29 | // ... 30 | } -------------------------------------------------------------------------------- /code/08/basic-proptypes.js: -------------------------------------------------------------------------------- 1 | Clock.propTypes = { 2 | title: React.PropTypes.string, 3 | count: React.PropTypes.number, 4 | isOn: React.PropTypes.bool, 5 | onDisplay: React.PropTypes.func, 6 | symbol: React.PropTypes.symbol, 7 | user: React.PropTypes.object, 8 | 9 | name: React.PropTypes.node 10 | } -------------------------------------------------------------------------------- /code/08/collection-proptypes.js: -------------------------------------------------------------------------------- 1 | Clock.propTypes = { 2 | counts: React.PropTypes.array, 3 | users: React.PropTypes.arrayOf(React.PropTypes.object), 4 | alarmColor: React.PropTypes.oneOf(['red', 'blue']), 5 | description: React.PropTypes.oneOfType([ 6 | React.PropTypes.string, 7 | React.PropTypes.instanceOf(Title) 8 | ]), 9 | } -------------------------------------------------------------------------------- /code/08/element-proptypes.js: -------------------------------------------------------------------------------- 1 | Clock.propTypes = { 2 | displayEle: React.PropTypes.element 3 | } -------------------------------------------------------------------------------- /code/08/object-proptypes.js: -------------------------------------------------------------------------------- 1 | Clock.propTypes = { 2 | basicObject: React.PropTypes.object, 3 | 4 | numbers: React.PropTypes 5 | .objectOf(React.PropTypes.numbers), 6 | 7 | messages: React.PropTypes 8 | .instanceOf(Message), 9 | 10 | contactList: React.PropTypes.shape({ 11 | name: React.PropTypes.string, 12 | phone: React.PropTypes.string, 13 | }) 14 | } -------------------------------------------------------------------------------- /code/08/proptypes1.js: -------------------------------------------------------------------------------- 1 | class Clock extends React.Component { 2 | // ... 3 | } 4 | 5 | Clock.propTypes = { 6 | // key is the name of the prop and 7 | // value is the PropType 8 | } -------------------------------------------------------------------------------- /code/09/header1.js: -------------------------------------------------------------------------------- 1 | class Header extends React.Component { 2 | render() { 3 | return ( 4 |
10 |
11 |
12 |
13 |
14 |
15 | 16 | {this.props.title} 17 | 18 | 19 | 20 |
21 |
22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /code/10/header-no-click.js: -------------------------------------------------------------------------------- 1 | class Header extends React.Component { 2 | render() { 3 | // Classes to add to the element 4 | let searchInputClasses = ["searchInput"]; 5 | 6 | // Update the class array if the state is visible 7 | if (this.state.searchVisible) { 8 | searchInputClasses.push("active"); 9 | } 10 | 11 | return ( 12 |
13 |
14 | 15 | 16 | {this.props.title} 17 | 18 | 19 | 23 | 24 |
25 |
26 | ) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /code/10/mousemove.js: -------------------------------------------------------------------------------- 1 | class MouseMove extends React.Component { 2 | constructor(props) { 3 | super(props); 4 | this.state = { 5 | x: -1, 6 | y: -1 7 | } 8 | } 9 | mouseMoved(e) { 10 | this.setState({ 11 | x: e.screenX, 12 | y: e.screenY 13 | }) 14 | } 15 | render() { 16 | const {x, y} = this.state; 17 | return ( 18 |
19 | Mouse is at {x}, {y} 20 |
21 | ) 22 | } 23 | } -------------------------------------------------------------------------------- /code/10/search-form.js: -------------------------------------------------------------------------------- 1 | class SearchForm extends React.Component { 2 | static propTypes = { 3 | onSubmit: T.func.isRequired, 4 | searchVisible: T.bool 5 | } 6 | 7 | static defaultProps = { 8 | onSubmit: () => {}, 9 | searchVisible: false 10 | } 11 | 12 | constructor(props) { 13 | super(props); 14 | 15 | this.state = { 16 | searchText: '' 17 | } 18 | } 19 | 20 | updateSearchInput(e) { 21 | const val = e.target.value; 22 | this.setState({ 23 | searchText: val 24 | }); 25 | } 26 | 27 | submitForm(e) { 28 | e.preventDefault(); 29 | 30 | const {searchText} = this.state; 31 | this.props.onSubmit(searchText); 32 | } 33 | 34 | render() { 35 | const {searchVisible, className} = this.props; 36 | 37 | return ( 38 |
39 | 46 |
47 | ); 48 | } 49 | } -------------------------------------------------------------------------------- /day-01/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-01/cover.jpg -------------------------------------------------------------------------------- /day-01/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello world 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /day-02/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-02/cover.jpg -------------------------------------------------------------------------------- /day-02/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello world 6 | 7 | 9 | 11 | 12 | 13 | 14 | 15 |
16 |
17 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /day-03/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-03/cover.jpg -------------------------------------------------------------------------------- /day-03/public/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello world 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /day-03/public/app2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello world 2 7 | 8 | 10 | 12 | 13 | 14 | 15 | 16 |
17 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /day-04/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-04/cover.jpg -------------------------------------------------------------------------------- /day-04/public/assets/images/breakdown-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-04/public/assets/images/breakdown-2.jpg -------------------------------------------------------------------------------- /day-04/public/assets/images/breakdown-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-04/public/assets/images/breakdown-2.png -------------------------------------------------------------------------------- /day-04/public/assets/images/breakdown.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-04/public/assets/images/breakdown.jpg -------------------------------------------------------------------------------- /day-04/public/assets/images/breakdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-04/public/assets/images/breakdown.png -------------------------------------------------------------------------------- /day-04/public/assets/images/part4.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-04/public/assets/images/part4.sketch -------------------------------------------------------------------------------- /day-05/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-05/cover.jpg -------------------------------------------------------------------------------- /day-06/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-06/cover.jpg -------------------------------------------------------------------------------- /day-06/public/Clock.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --firstColor: rgba(0, 169, 158, 1); 3 | --secondColor: rgba(0, 191, 150, 1); 4 | --textColor: #fff; 5 | } 6 | 7 | .clock { 8 | position: relative; 9 | border-radius: 0.5em; 10 | margin: 10px auto; 11 | font-family: "Open Sans", sans-serif; 12 | text-align: center; 13 | font-size: 60px; 14 | color: var(--textColor); 15 | line-height: 2em; 16 | background: #eee; 17 | /* Old browsers */ 18 | background: var(--firstColor); 19 | } 20 | 21 | @media only screen and (min-width: 700px) and (max-width: 1000px) { 22 | .clock { 23 | font-size: 50px; 24 | } 25 | } 26 | 27 | @media only screen and (min-width: 500px) and (max-width: 699px) { 28 | .clock { 29 | font-size: 45px; 30 | } 31 | } 32 | 33 | @media only screen and (min-width: 200px) and (max-width: 499px) { 34 | .clock { 35 | font-size: 40px; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /day-07/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-07/cover.jpg -------------------------------------------------------------------------------- /day-08/BasicProptypes.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | Clock.propTypes = { 4 | title: PropTypes.string, 5 | count: PropTypes.number, 6 | isOn: PropTypes.bool, 7 | onDisplay: PropTypes.func, 8 | symbol: PropTypes.symbol, 9 | user: PropTypes.object, 10 | 11 | name: PropTypes.node 12 | }; 13 | -------------------------------------------------------------------------------- /day-08/CollectionProptypes.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | Clock.propTypes = { 4 | counts: PropTypes.array, 5 | users: PropTypes.arrayOf(PropTypes.object), 6 | alarmColor: PropTypes.oneOf(['red', 'blue']), 7 | description: PropTypes.oneOfType([ 8 | PropTypes.string, 9 | PropTypes.instanceOf(Title) 10 | ]) 11 | }; 12 | -------------------------------------------------------------------------------- /day-08/ElementProptypes.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | Clock.propTypes = { 4 | displayEle: PropTypes.element 5 | }; 6 | -------------------------------------------------------------------------------- /day-08/ObjectProptypes.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types'; 2 | 3 | Clock.propTypes = { 4 | basicObject: PropTypes.object, 5 | 6 | numbers: PropTypes.objectOf(PropTypes.numbers), 7 | 8 | messages: PropTypes.instanceOf(Message), 9 | 10 | contactList: PropTypes.shape({ 11 | name: PropTypes.string, 12 | phone: PropTypes.string 13 | }) 14 | }; 15 | -------------------------------------------------------------------------------- /day-08/Proptypes1.js: -------------------------------------------------------------------------------- 1 | class Clock extends React.Component { 2 | // ... 3 | } 4 | 5 | Clock.propTypes = { 6 | // key is the name of the prop and 7 | // value is the PropType 8 | } -------------------------------------------------------------------------------- /day-08/UserLink.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | class UserLink extends React.Component { 4 | render() { 5 | const { user } = this.props 6 | return ( 7 |
8 | Welcome back {user.name} 9 |
10 | ) 11 | } 12 | } 13 | 14 | UserLink.propTypes = { 15 | user: (props, propName, componentName) => { 16 | if (!props[propName] || !props[propName].name) { 17 | return new Error( 18 | "Invalid " + propName + ": No name property defined for component " + componentName 19 | ) 20 | } 21 | } 22 | } 23 | 24 | export default UserLink -------------------------------------------------------------------------------- /day-08/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-08/cover.jpg -------------------------------------------------------------------------------- /day-09/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-09/cover.jpg -------------------------------------------------------------------------------- /day-09/public/styles.css: -------------------------------------------------------------------------------- 1 | .demo .notificationsFrame .header { 2 | background: rgba(251, 202, 43, 1); 3 | } 4 | .demo .notificationsFrame .header .searchIcon, 5 | .demo .notificationsFrame .header .title { 6 | color: #333333; 7 | } 8 | 9 | .demo .notificationsFrame .header .menuIcon .dashTop, 10 | .demo .notificationsFrame .header .menuIcon .dashBottom, 11 | .demo .notificationsFrame .header .menuIcon .circle { 12 | background-color: #333333; 13 | } 14 | -------------------------------------------------------------------------------- /day-09/public/text-color.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Color Blue 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
17 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /day-10/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-10/cover.jpg -------------------------------------------------------------------------------- /day-10/public/mouse-move.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Mouse Move 7 | 8 | 9 |
10 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /day-10/public/styles.css: -------------------------------------------------------------------------------- 1 | .demo { 2 | max-width: 800px; 3 | margin: 20px auto; 4 | } 5 | .eventContainer ul { 6 | margin: 0; 7 | padding: 0; 8 | } 9 | .eventContainer ul li.eventListing { 10 | list-style-type: none; 11 | font-size: 0.9em; 12 | position: relative; 13 | z-index: 2; 14 | padding: 20px 10px; 15 | box-shadow: 0px 1px 1px 0 rgba(0, 0, 0, 0.3); 16 | } 17 | .eventContainer ul li.eventListing .reset, 18 | .eventContainer ul li.eventListing .name, 19 | .eventContainer ul li.eventListing .trigger { 20 | position: absolute; 21 | top: 8px; 22 | } 23 | .eventContainer ul li.eventListing .reset { 24 | left: 5px; 25 | } 26 | .eventContainer ul li.eventListing .name { 27 | left: 35px; 28 | } 29 | .eventContainer ul li.eventListing .trigger { 30 | right: 15px; 31 | } 32 | .eventContainer ul li.eventListing .trigger i { 33 | color: rgba(95, 152, 205, 1); 34 | } 35 | -------------------------------------------------------------------------------- /day-11/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-11/cover.jpg -------------------------------------------------------------------------------- /day-12/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /day-12/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-12/cover.jpg -------------------------------------------------------------------------------- /day-12/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-12", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-scripts": "3.3.0" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "build": "react-scripts build", 16 | "test": "react-scripts test", 17 | "eject": "react-scripts eject" 18 | }, 19 | "eslintConfig": { 20 | "extends": "react-app" 21 | }, 22 | "browserslist": { 23 | "production": [ 24 | ">0.2%", 25 | "not dead", 26 | "not op_mini all" 27 | ], 28 | "development": [ 29 | "last 1 chrome version", 30 | "last 1 firefox version", 31 | "last 1 safari version" 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /day-12/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-12/public/favicon.ico -------------------------------------------------------------------------------- /day-12/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-12/public/logo192.png -------------------------------------------------------------------------------- /day-12/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-12/public/logo512.png -------------------------------------------------------------------------------- /day-12/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-12/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-12/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-12/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import Header from "./components/Header"; 4 | import Content from "./components/Content"; 5 | 6 | function App() { 7 | return ( 8 |
9 |
10 | 11 |
12 | ); 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /day-12/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-12/src/components/Content.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | class Content extends Component { 4 | render() { 5 | return

Content goes here

; 6 | } 7 | } 8 | 9 | export default Content; 10 | -------------------------------------------------------------------------------- /day-12/src/components/Header.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | 3 | class Header extends Component { 4 | render() { 5 | return ( 6 | 9 | ); 10 | } 11 | } 12 | 13 | export default Header; 14 | -------------------------------------------------------------------------------- /day-12/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-12/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /day-12/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-13/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-13/cover.jpg -------------------------------------------------------------------------------- /day-13/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-13", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-scripts": "3.3.0" 12 | }, 13 | "scripts": { 14 | "start": "react-scripts start", 15 | "build": "react-scripts build", 16 | "test": "react-scripts test", 17 | "eject": "react-scripts eject" 18 | }, 19 | "eslintConfig": { 20 | "extends": "react-app" 21 | }, 22 | "browserslist": { 23 | "production": [ 24 | ">0.2%", 25 | "not dead", 26 | "not op_mini all" 27 | ], 28 | "development": [ 29 | "last 1 chrome version", 30 | "last 1 firefox version", 31 | "last 1 safari version" 32 | ] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /day-13/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-13/public/favicon.ico -------------------------------------------------------------------------------- /day-13/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-13/public/logo192.png -------------------------------------------------------------------------------- /day-13/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-13/public/logo512.png -------------------------------------------------------------------------------- /day-13/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-13/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-13/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-13/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const a = [1, 10, 100, 1000, 10000]; 4 | const App = props => { 5 | return ( 6 |
    7 | {React.Children.map(a, i => ( 8 |
  • {i}
  • 9 | ))} 10 |
11 | ); 12 | }; 13 | 14 | export default App; 15 | -------------------------------------------------------------------------------- /day-13/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-13/src/components/Repeater.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const a = [1, 10, 100, 1000, 10000]; 4 | const Repeater = () => { 5 | return ( 6 |
    7 | {a.map(i => { 8 | return
  • {i}
  • ; 9 | })} 10 |
11 | ); 12 | }; 13 | 14 | export default Repeater; 15 | -------------------------------------------------------------------------------- /day-13/src/components/ShowA.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | const a = 10; 3 | const ShowA = () =>
{a}
; 4 | const MultipleA = () =>
{a * a}
; 5 | -------------------------------------------------------------------------------- /day-13/src/components/Timer/Ampm.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Ampm = ({hours}) => ({hours >= 12 ? 'pm' : 'am'}) 4 | 5 | export default Ampm -------------------------------------------------------------------------------- /day-13/src/components/Timer/CleanerFormatter.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import Hour from "./Hour"; 4 | import Minute from "./Minute"; 5 | import Second from "./Second"; 6 | import Ampm from "./Ampm"; 7 | import Separator from "./Separator"; 8 | 9 | const Formatter = props => { 10 | let children = props.format.split("").map(e => { 11 | if (e === "h") { 12 | return ; 13 | } else if (e === "m") { 14 | return ; 15 | } else if (e === "s") { 16 | return ; 17 | } else if (e === "p") { 18 | return ; 19 | } else if (e === " ") { 20 | return ; 21 | } else { 22 | return ; 23 | } 24 | }); 25 | return ( 26 | 27 | {React.Children.map(children, c => React.cloneElement(c, props))} 28 | 29 | ); 30 | }; 31 | 32 | export default Formatter; 33 | -------------------------------------------------------------------------------- /day-13/src/components/Timer/Formatter.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Hour from './Hour'; 4 | import Minute from './Minute'; 5 | import Second from './Second'; 6 | import Ampm from './Ampm'; 7 | import Separator from './Separator'; 8 | 9 | const Formatter = (props) => { 10 | let children = props.format.split('').map((e, idx) => { 11 | if (e === 'h') { 12 | return 13 | } else if (e === 'm') { 14 | return 15 | } else if (e === 's') { 16 | return 17 | } else if (e === 'p') { 18 | return 19 | } else if (e === ' ') { 20 | return ; 21 | } else { 22 | return 23 | } 24 | }); 25 | 26 | return {children}; 27 | } 28 | 29 | export default Formatter -------------------------------------------------------------------------------- /day-13/src/components/Timer/Hour.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Hour = (props) => { 4 | let {hours} = props; 5 | if (hours === 0) { hours = 12; } 6 | if (props.twelveHours) { hours -= 12; } 7 | return ({hours}) 8 | } 9 | 10 | export default Hour -------------------------------------------------------------------------------- /day-13/src/components/Timer/Minute.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Minute = ({minutes}) => ({minutes<10 && '0'}{minutes}) 4 | 5 | export default Minute -------------------------------------------------------------------------------- /day-13/src/components/Timer/Second.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Second = ({seconds}) => ({seconds<10 && '0'}{seconds}) 4 | 5 | export default Second -------------------------------------------------------------------------------- /day-13/src/components/Timer/Separator.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const Separator = ({separator}) => ({separator || ':'}) 4 | 5 | export default Separator -------------------------------------------------------------------------------- /day-13/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-13/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /day-13/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-14/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-14/cover.jpg -------------------------------------------------------------------------------- /day-15/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-15/cover.jpg -------------------------------------------------------------------------------- /day-15/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-15", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-scripts": "3.3.0", 12 | "whatwg-fetch": "^3.0.0" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /day-15/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-15/public/favicon.ico -------------------------------------------------------------------------------- /day-15/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-15/public/logo192.png -------------------------------------------------------------------------------- /day-15/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-15/public/logo512.png -------------------------------------------------------------------------------- /day-15/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-15/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-15/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-15/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "whatwg-fetch"; 3 | 4 | const App = props => { 5 | return
; 6 | }; 7 | 8 | export default App; 9 | -------------------------------------------------------------------------------- /day-15/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-15/src/getCurrentTimeCallback.js: -------------------------------------------------------------------------------- 1 | export default function getCurrentTimeCallback(callback) { 2 | // Get the current 'global' time from an API 3 | return setTimeout(function() { 4 | var currentTime = new Date(); 5 | callback(currentTime); 6 | }, 2000); 7 | } 8 | -------------------------------------------------------------------------------- /day-15/src/getCurrentTimeHandlerId.js: -------------------------------------------------------------------------------- 1 | export default function getCurrentTimeHandlerId() { 2 | // Get the current 'global' time from an API 3 | return setTimeout(function() { 4 | return new Date(); 5 | }, 2000); 6 | } 7 | -------------------------------------------------------------------------------- /day-15/src/getCurrentTimeOnFail.js: -------------------------------------------------------------------------------- 1 | export default function getCurrentTimeOnFail(onSuccess, onFail) { 2 | // Get the current 'global' time from an API 3 | return setTimeout(function() { 4 | // randomly decide if the date is retrieved or not 5 | var didSucceed = Math.random() >= 0.5; 6 | if (didSucceed) { 7 | var currentTime = new Date(); 8 | onSuccess(currentTime); 9 | } else { 10 | onFail("Unknown error"); 11 | } 12 | }, 2000); 13 | } 14 | -------------------------------------------------------------------------------- /day-15/src/getCurrentTimePromise.js: -------------------------------------------------------------------------------- 1 | export default function getCurrentTimePromise() { 2 | // Get the current 'global' time from an API using Promise 3 | return new Promise((resolve, reject) => { 4 | setTimeout(function() { 5 | var didSucceed = Math.random() >= 0.5; 6 | didSucceed ? resolve(new Date()) : reject("Error"); 7 | }, 2000); 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /day-15/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-15/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-16/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-16/cover.jpg -------------------------------------------------------------------------------- /day-16/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-16", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-scripts": "3.3.0", 12 | "whatwg-fetch": "^3.0.0" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": "react-app" 22 | }, 23 | "browserslist": { 24 | "production": [ 25 | ">0.2%", 26 | "not dead", 27 | "not op_mini all" 28 | ], 29 | "development": [ 30 | "last 1 chrome version", 31 | "last 1 firefox version", 32 | "last 1 safari version" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /day-16/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-16/public/favicon.ico -------------------------------------------------------------------------------- /day-16/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-16/public/logo192.png -------------------------------------------------------------------------------- /day-16/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-16/public/logo512.png -------------------------------------------------------------------------------- /day-16/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-16/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-16/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-16/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-16/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-16/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "./index.css"; 4 | import App from "./App"; 5 | import * as serviceWorker from "./serviceWorker"; 6 | 7 | ReactDOM.render(, document.getElementById("root")); 8 | 9 | // If you want your app to work offline and load faster, you can change 10 | // unregister() to register() below. Note this comes with some pitfalls. 11 | // Learn more about service workers: https://bit.ly/CRA-PWA 12 | serviceWorker.unregister(); 13 | -------------------------------------------------------------------------------- /day-16/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-17/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-17/cover.jpg -------------------------------------------------------------------------------- /day-17/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-17", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-frame-component": "^4.1.1", 12 | "react-router-dom": "^5.1.2", 13 | "react-scripts": "3.3.0" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /day-17/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-17/public/favicon.ico -------------------------------------------------------------------------------- /day-17/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-17/public/logo192.png -------------------------------------------------------------------------------- /day-17/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-17/public/logo512.png -------------------------------------------------------------------------------- /day-17/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-17/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-17/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-17/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route } from "react-router-dom"; 4 | 5 | const Home = () => ( 6 |
7 |

Welcome home

8 |
9 | ); 10 | 11 | class App extends React.Component { 12 | render() { 13 | return ( 14 | 15 | 16 | 17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /day-17/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-17/src/SimpleRouter.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route } from "react-router-dom"; 4 | 5 | const Home = () => ( 6 |
7 |

Welcome home

8 |
9 | ); 10 | 11 | class App extends React.Component { 12 | render() { 13 | return ( 14 | 15 | 16 | 17 | ); 18 | } 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /day-17/src/TwoLinkedRoutes.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route, Link } from "react-router-dom"; 4 | 5 | const Home = () => ( 6 |
7 |

Welcome home

8 | Go to about 9 |
10 | ); 11 | const About = () => ( 12 |
13 |

About

14 | Go home 15 |
16 | ); 17 | 18 | class App extends React.Component { 19 | render() { 20 | return ( 21 | 22 |
23 | 24 | 25 |
26 |
27 | ); 28 | } 29 | } 30 | 31 | export default App; 32 | -------------------------------------------------------------------------------- /day-17/src/TwoLinkedSingleRoutes.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; 4 | 5 | const Home = () => ( 6 |
7 |

Welcome home

8 | Go to about 9 |
10 | ); 11 | const About = () => ( 12 |
13 |

About

14 | Go home 15 |
16 | ); 17 | 18 | class App extends React.Component { 19 | render() { 20 | return ( 21 | 22 | 23 | 24 | 25 | 26 | 27 | ); 28 | } 29 | } 30 | 31 | export default App; 32 | -------------------------------------------------------------------------------- /day-17/src/TwoRoutes.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route } from "react-router-dom"; 4 | 5 | const Home = () => ( 6 |
7 |

Welcome home

8 |
9 | ); 10 | const About = () => ( 11 |
12 |

About

13 |
14 | ); 15 | 16 | class App extends React.Component { 17 | render() { 18 | return ( 19 | 20 |
21 | 22 | 23 |
24 |
25 | ); 26 | } 27 | } 28 | 29 | export default App; 30 | -------------------------------------------------------------------------------- /day-17/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-17/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-18/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-18/cover.jpg -------------------------------------------------------------------------------- /day-19/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-19/cover.jpg -------------------------------------------------------------------------------- /day-19/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-19", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-redux": "^7.1.3", 12 | "react-router-dom": "^5.1.2", 13 | "react-scripts": "3.3.0", 14 | "redux": "^4.0.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /day-19/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-19/public/favicon.ico -------------------------------------------------------------------------------- /day-19/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-19/public/logo192.png -------------------------------------------------------------------------------- /day-19/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-19/public/logo512.png -------------------------------------------------------------------------------- /day-19/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-19/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-19/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-19/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-19/src/containers/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; 4 | 5 | // We'll load our views from the `src/views` 6 | // directory 7 | import Home from "./views/Home/Home"; 8 | import About from "./views/About/About"; 9 | 10 | const App = props => { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /day-19/src/containers/Root.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Provider } from "react-redux"; 3 | import App from "./App"; 4 | import configureStore from "../redux/configureStore"; 5 | 6 | const Root = props => { 7 | const store = configureStore(); 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default Root; 16 | -------------------------------------------------------------------------------- /day-19/src/containers/views/About/About.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const About = () => ( 5 |
6 |

About

7 | Go home 8 |
9 | ); 10 | 11 | export default About; 12 | -------------------------------------------------------------------------------- /day-19/src/containers/views/Home/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import { connect } from "react-redux"; 4 | 5 | const mapStateToProps = state => { 6 | return { 7 | currentTime: state.currentTime 8 | }; 9 | }; 10 | 11 | const Home = props => ( 12 |
13 |

Welcome home

14 |

Current time: {props.currentTime}

15 | Go to about 16 |
17 | ); 18 | 19 | export default connect(mapStateToProps)(Home); 20 | -------------------------------------------------------------------------------- /day-19/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-19/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Root from "./containers/Root"; 4 | import "./index.css"; 5 | 6 | ReactDOM.render(, document.getElementById("root")); 7 | -------------------------------------------------------------------------------- /day-19/src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore } from "redux"; 2 | import { rootReducer, initialState } from "./reducers"; 3 | 4 | export const configureStore = () => { 5 | const store = createStore( 6 | rootReducer, // root reducer 7 | initialState // our initialState 8 | ); 9 | return store; 10 | }; 11 | export default configureStore; 12 | -------------------------------------------------------------------------------- /day-19/src/redux/reducers.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | // Initial (starting) state 3 | export const initialState = { 4 | currentTime: new Date().toString() 5 | }; 6 | 7 | // Our root reducer starts with the initial state 8 | // and must return a representation of the next state 9 | export const rootReducer = (state = initialState, action) => { 10 | switch (action.type) { 11 | case types.FETCH_NEW_TIME: 12 | return { 13 | ...state, 14 | currentTime: action.payload 15 | }; 16 | default: 17 | return state; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /day-19/src/redux/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_NEW_TIME = "FETCH_NEW_TIME"; 2 | -------------------------------------------------------------------------------- /day-19/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-20/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-20/cover.jpg -------------------------------------------------------------------------------- /day-20/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-20", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-redux": "^7.1.3", 12 | "react-router-dom": "^5.1.2", 13 | "react-scripts": "3.3.0", 14 | "redux": "^4.0.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /day-20/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-20/public/favicon.ico -------------------------------------------------------------------------------- /day-20/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-20/public/logo192.png -------------------------------------------------------------------------------- /day-20/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-20/public/logo512.png -------------------------------------------------------------------------------- /day-20/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-20/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-20/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-20/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-20/src/containers/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; 4 | 5 | // We'll load our views from the `src/views` 6 | // directory 7 | import Home from "./views/Home/Home"; 8 | import About from "./views/About/About"; 9 | 10 | const App = props => { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /day-20/src/containers/Root.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Provider } from "react-redux"; 3 | import App from "./App"; 4 | import configureStore from "../redux/configureStore"; 5 | 6 | const Root = props => { 7 | const store = configureStore(); 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default Root; 16 | -------------------------------------------------------------------------------- /day-20/src/containers/views/About/About.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const About = () => ( 5 |
6 |

About

7 | Go home 8 |
9 | ); 10 | 11 | export default About; 12 | -------------------------------------------------------------------------------- /day-20/src/containers/views/Home/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | // import { Link } from "react-router-dom"; 3 | import { connect } from "react-redux"; 4 | import { fetchNewTime } from "../../../redux/actionCreators"; 5 | 6 | const mapStateToProps = state => { 7 | return { 8 | currentTime: state.time.currentTime 9 | }; 10 | }; 11 | 12 | const mapDispatchToProps = dispatch => ({ 13 | updateTime: () => dispatch(fetchNewTime()) 14 | }); 15 | 16 | const Home = props => ( 17 |
18 |

Welcome home

19 |

Current time: {props.currentTime}

20 | 21 | {/* Go to about */} 22 |
23 | ); 24 | 25 | export default connect(mapStateToProps, mapDispatchToProps)(Home); 26 | -------------------------------------------------------------------------------- /day-20/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-20/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Root from "./containers/Root"; 4 | import "./index.css"; 5 | 6 | ReactDOM.render(, document.getElementById("root")); 7 | -------------------------------------------------------------------------------- /day-20/src/redux/actionCreators.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const fetchNewTime = () => ({ 4 | type: types.FETCH_NEW_TIME, 5 | payload: new Date().toString() 6 | }); 7 | 8 | export const login = user => ({ 9 | type: types.LOGIN, 10 | payload: user 11 | }); 12 | 13 | export const logout = () => ({ 14 | type: types.LOGOUT 15 | }); 16 | -------------------------------------------------------------------------------- /day-20/src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, combineReducers } from "redux"; 2 | 3 | import { rootReducer, initialState } from "./reducers"; 4 | import { reducer, initialState as userInitialState } from "./currentUser"; 5 | 6 | export const configureStore = () => { 7 | const store = createStore( 8 | combineReducers({ 9 | time: rootReducer, 10 | user: reducer 11 | }), // root reducer 12 | { 13 | time: initialState, 14 | user: userInitialState 15 | } // our initialState 16 | ); 17 | 18 | return store; 19 | }; 20 | 21 | export default configureStore; 22 | -------------------------------------------------------------------------------- /day-20/src/redux/currentUser.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const initialState = { 4 | user: {}, 5 | loggedIn: false 6 | }; 7 | 8 | export const reducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case types.LOGIN: 11 | return { 12 | ...state, 13 | user: action.payload, 14 | loggedIn: true 15 | }; 16 | case types.LOGOUT: 17 | return { 18 | ...state, 19 | user: {}, 20 | loggedIn: false 21 | }; 22 | default: 23 | return state; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /day-20/src/redux/reducers.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | // Initial (starting) state 3 | export const initialState = { 4 | currentTime: new Date().toString() 5 | }; 6 | 7 | // Our root reducer starts with the initial state 8 | // and must return a representation of the next state 9 | export const rootReducer = (state = initialState, action) => { 10 | switch (action.type) { 11 | case types.FETCH_NEW_TIME: 12 | return { 13 | ...state, 14 | currentTime: action.payload 15 | }; 16 | default: 17 | return state; 18 | } 19 | }; 20 | -------------------------------------------------------------------------------- /day-20/src/redux/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_NEW_TIME = "FETCH_NEW_TIME"; 2 | export const LOGIN = "USER_LOGIN"; 3 | export const LOGOUT = "USER_LOGOUT"; 4 | -------------------------------------------------------------------------------- /day-20/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-21/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-21/cover.jpg -------------------------------------------------------------------------------- /day-21/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-21", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "react": "^16.12.0", 10 | "react-dom": "^16.12.0", 11 | "react-redux": "^7.1.3", 12 | "react-router-dom": "^5.1.2", 13 | "react-scripts": "3.3.0", 14 | "redux": "^4.0.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": "react-app" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /day-21/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-21/public/favicon.ico -------------------------------------------------------------------------------- /day-21/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-21/public/logo192.png -------------------------------------------------------------------------------- /day-21/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-21/public/logo512.png -------------------------------------------------------------------------------- /day-21/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-21/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-21/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-21/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "@testing-library/react"; 3 | import App from "./containers/Root"; 4 | 5 | test("renders welcom home text", () => { 6 | const { getByText } = render(); 7 | const textElement = getByText(/welcome home/i); 8 | expect(textElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-21/src/containers/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; 4 | 5 | // We'll load our views from the `src/views` 6 | // directory 7 | import Home from "./views/Home/Home"; 8 | import About from "./views/About/About"; 9 | 10 | const App = props => { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /day-21/src/containers/Root.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Provider } from "react-redux"; 3 | import App from "./App"; 4 | import configureStore from "../redux/configureStore"; 5 | 6 | const Root = props => { 7 | const store = configureStore(); 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default Root; 16 | -------------------------------------------------------------------------------- /day-21/src/containers/views/About/About.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const About = () => ( 5 |
6 |

About

7 | Go home 8 |
9 | ); 10 | 11 | export default About; 12 | -------------------------------------------------------------------------------- /day-21/src/containers/views/Home/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | // import { Link } from "react-router-dom"; 3 | import { connect } from "react-redux"; 4 | import { fetchNewTime } from "../../../redux/actionCreators"; 5 | 6 | const mapStateToProps = state => { 7 | return { 8 | currentTime: state.currentTime.currentTime 9 | }; 10 | }; 11 | 12 | const mapDispatchToProps = dispatch => ({ 13 | updateTime: () => dispatch(fetchNewTime()) 14 | }); 15 | 16 | const Home = props => ( 17 |
18 |

Welcome home

19 |

Current time: {props.currentTime}

20 | 21 | {/* Go to about */} 22 |
23 | ); 24 | 25 | export default connect(mapStateToProps, mapDispatchToProps)(Home); 26 | -------------------------------------------------------------------------------- /day-21/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-21/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Root from "./containers/Root"; 4 | import "./index.css"; 5 | 6 | ReactDOM.render(, document.getElementById("root")); 7 | -------------------------------------------------------------------------------- /day-21/src/redux/actionCreators.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | const host = "https://andthetimeis.com"; 4 | export const fetchNewTime = (timezone = "pst", str = "now") => ({ 5 | type: types.FETCH_NEW_TIME, 6 | payload: new Date().toString(), 7 | meta: { 8 | type: "api", 9 | url: host + "/" + timezone + "/" + str + ".json" 10 | } 11 | }); 12 | 13 | export const login = user => ({ 14 | type: types.LOGIN, 15 | payload: user 16 | }); 17 | 18 | export const logout = () => ({ 19 | type: types.LOGOUT 20 | }); 21 | -------------------------------------------------------------------------------- /day-21/src/redux/apiMiddleware.js: -------------------------------------------------------------------------------- 1 | const apiMiddleware = store => next => action => { 2 | if (!action.meta || action.meta.type !== "api") { 3 | return next(action); 4 | } 5 | // This is an api request 6 | 7 | // Find the request URL and compose request options from meta 8 | const { url } = action.meta; 9 | const fetchOptions = Object.assign({}, action.meta); 10 | 11 | // Make the request 12 | fetch(url, fetchOptions) 13 | // convert the response to json 14 | .then(resp => resp.json()) 15 | .then(json => { 16 | if (typeof action.meta.onSuccess === "function") { 17 | action.meta.onSuccess(json); 18 | } 19 | return json; // For the next promise in the chain 20 | }) 21 | .then(json => { 22 | // respond back to the user 23 | // by dispatching the original action without 24 | // the meta object 25 | let newAction = Object.assign({}, action, { 26 | payload: json.dateString 27 | }); 28 | delete newAction.meta; 29 | store.dispatch(newAction); 30 | }); 31 | }; 32 | 33 | export default apiMiddleware; 34 | -------------------------------------------------------------------------------- /day-21/src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from "redux"; 2 | 3 | import { rootReducer, initialState } from "./reducers"; 4 | import loggingMiddleware from "./loggingMiddleware"; 5 | import apiMiddleware from "./apiMiddleware"; 6 | 7 | export const configureStore = () => { 8 | const store = createStore( 9 | rootReducer, 10 | initialState, 11 | applyMiddleware(loggingMiddleware, apiMiddleware) 12 | ); 13 | return store; 14 | }; 15 | 16 | export default configureStore; 17 | -------------------------------------------------------------------------------- /day-21/src/redux/currentTime.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const initialState = { 4 | currentTime: new Date().toString() 5 | }; 6 | 7 | export const reducer = (state = initialState, action) => { 8 | switch (action.type) { 9 | case types.FETCH_NEW_TIME: 10 | return { ...state, currentTime: action.payload }; 11 | default: 12 | return state; 13 | } 14 | }; 15 | 16 | export default reducer; 17 | -------------------------------------------------------------------------------- /day-21/src/redux/currentUser.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const initialState = { 4 | user: {}, 5 | loggedIn: false 6 | }; 7 | 8 | export const reducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case types.LOGIN: 11 | return { 12 | ...state, 13 | user: action.payload, 14 | loggedIn: true 15 | }; 16 | case types.LOGOUT: 17 | return { 18 | ...state, 19 | user: {}, 20 | loggedIn: false 21 | }; 22 | default: 23 | return state; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /day-21/src/redux/loggingMiddleware.js: -------------------------------------------------------------------------------- 1 | const loggingMiddleware = store => next => action => { 2 | // Our middleware 3 | console.log(`Redux Log:`, action); 4 | // call the next function 5 | next(action); 6 | }; 7 | 8 | export default loggingMiddleware; 9 | -------------------------------------------------------------------------------- /day-21/src/redux/reducers.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from "redux"; 2 | 3 | import * as currentUser from "./currentUser"; 4 | import * as currentTime from "./currentTime"; 5 | 6 | export const rootReducer = combineReducers({ 7 | currentTime: currentTime.reducer, 8 | currentUser: currentUser.reducer 9 | }); 10 | 11 | export const initialState = { 12 | currentTime: currentTime.initialState, 13 | currentUser: currentUser.initialState 14 | }; 15 | 16 | export default rootReducer; 17 | -------------------------------------------------------------------------------- /day-21/src/redux/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_NEW_TIME = "FETCH_NEW_TIME"; 2 | export const LOGIN = "USER_LOGIN"; 3 | export const LOGOUT = "USER_LOGOUT"; 4 | -------------------------------------------------------------------------------- /day-21/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-22/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-22/cover.jpg -------------------------------------------------------------------------------- /day-23/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-23/cover.jpg -------------------------------------------------------------------------------- /day-23/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-23", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "font-awesome": "^4.7.0", 7 | "moment": "^2.24.0", 8 | "react": "^16.12.0", 9 | "react-dom": "^16.12.0", 10 | "react-scripts": "3.3.0" 11 | }, 12 | "scripts": { 13 | "start": "react-scripts start", 14 | "build": "react-scripts build", 15 | "test": "react-scripts test --env=jsdom", 16 | "eject": "react-scripts eject" 17 | }, 18 | "eslintConfig": { 19 | "extends": "react-app" 20 | }, 21 | "browserslist": { 22 | "production": [ 23 | ">0.2%", 24 | "not dead", 25 | "not op_mini all" 26 | ], 27 | "development": [ 28 | "last 1 chrome version", 29 | "last 1 firefox version", 30 | "last 1 safari version" 31 | ] 32 | }, 33 | "devDependencies": { 34 | "babel-jest": "^24.9.0", 35 | "babel-preset-stage-0": "^6.24.1", 36 | "enzyme": "^3.10.0", 37 | "jest-cli": "^24.9.0", 38 | "react-addons-test-utils": "^15.6.2", 39 | "react-test-renderer": "^16.12.0", 40 | "redux-mock-store": "^1.5.4", 41 | "sinon": "^7.5.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /day-23/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-23/public/favicon.ico -------------------------------------------------------------------------------- /day-23/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-23/public/logo192.png -------------------------------------------------------------------------------- /day-23/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-23/public/logo512.png -------------------------------------------------------------------------------- /day-23/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-23/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-23/src/components/Timeline/__tests__/Timeline-test.js: -------------------------------------------------------------------------------- 1 | describe("Timeline", () => { 2 | it("passing test", () => { 3 | expect(true).toBeTruthy(); 4 | }); 5 | 6 | it("failing test", () => { 7 | expect(false).toBeFalsy(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /day-23/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "font-awesome/css/font-awesome.css"; 4 | 5 | import Timeline from "./components/Timeline/Timeline"; 6 | 7 | export const load = () => { 8 | ReactDOM.render(, document.getElementById("root")); 9 | }; 10 | 11 | try { 12 | load(); 13 | } catch (e) {} 14 | -------------------------------------------------------------------------------- /day-24/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-24/cover.jpg -------------------------------------------------------------------------------- /day-24/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-24", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "font-awesome": "^4.7.0", 7 | "moment": "^2.24.0", 8 | "react": "^16.12.0", 9 | "react-dom": "^16.12.0", 10 | "react-scripts": "3.3.0" 11 | }, 12 | "scripts": { 13 | "start": "react-scripts start", 14 | "build": "react-scripts build", 15 | "test": "react-scripts test --env=jsdom", 16 | "eject": "react-scripts eject" 17 | }, 18 | "eslintConfig": { 19 | "extends": "react-app" 20 | }, 21 | "browserslist": { 22 | "production": [ 23 | ">0.2%", 24 | "not dead", 25 | "not op_mini all" 26 | ], 27 | "development": [ 28 | "last 1 chrome version", 29 | "last 1 firefox version", 30 | "last 1 safari version" 31 | ] 32 | }, 33 | "devDependencies": { 34 | "babel-jest": "^24.9.0", 35 | "babel-preset-stage-0": "^6.24.1", 36 | "enzyme": "^3.10.0", 37 | "jest-cli": "^24.9.0", 38 | "react-addons-test-utils": "^15.6.2", 39 | "react-test-renderer": "^16.12.0", 40 | "redux-mock-store": "^1.5.4", 41 | "sinon": "^7.5.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /day-24/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-24/public/favicon.ico -------------------------------------------------------------------------------- /day-24/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-24/public/logo192.png -------------------------------------------------------------------------------- /day-24/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-24/public/logo512.png -------------------------------------------------------------------------------- /day-24/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-24/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-24/src/components/Timeline/__tests__/Timeline-test.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import TestUtils from "react-dom/test-utils"; 3 | import Timeline from "../Timeline"; 4 | 5 | describe("Timeline", () => { 6 | it("wraps content in a div with .notificationsFrame class", () => { 7 | const wrapper = TestUtils.renderIntoDocument(); 8 | const node = TestUtils.findRenderedDOMComponentWithClass( 9 | wrapper, 10 | "notificationsFrame" 11 | ); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /day-24/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "font-awesome/css/font-awesome.css"; 4 | 5 | import Timeline from "./components/Timeline/Timeline"; 6 | 7 | export const load = () => { 8 | ReactDOM.render(, document.getElementById("root")); 9 | }; 10 | 11 | try { 12 | load(); 13 | } catch (e) {} 14 | -------------------------------------------------------------------------------- /day-25/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-25/cover.jpg -------------------------------------------------------------------------------- /day-25/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-25", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "font-awesome": "^4.7.0", 7 | "moment": "^2.24.0", 8 | "react": "^16.12.0", 9 | "react-dom": "^16.12.0", 10 | "react-scripts": "3.3.0" 11 | }, 12 | "scripts": { 13 | "start": "react-scripts start", 14 | "build": "react-scripts build", 15 | "test": "react-scripts test --env=jsdom", 16 | "eject": "react-scripts eject" 17 | }, 18 | "eslintConfig": { 19 | "extends": "react-app" 20 | }, 21 | "browserslist": { 22 | "production": [ 23 | ">0.2%", 24 | "not dead", 25 | "not op_mini all" 26 | ], 27 | "development": [ 28 | "last 1 chrome version", 29 | "last 1 firefox version", 30 | "last 1 safari version" 31 | ] 32 | }, 33 | "devDependencies": { 34 | "babel-jest": "^24.9.0", 35 | "babel-preset-stage-0": "^6.24.1", 36 | "enzyme": "^3.10.0", 37 | "enzyme-adapter-react-16": "^1.15.1", 38 | "jest-cli": "^24.9.0", 39 | "react-addons-test-utils": "^15.6.2", 40 | "react-test-renderer": "^16.12.0", 41 | "redux-mock-store": "^1.5.4", 42 | "sinon": "^7.5.0" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /day-25/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-25/public/favicon.ico -------------------------------------------------------------------------------- /day-25/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-25/public/logo192.png -------------------------------------------------------------------------------- /day-25/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-25/public/logo512.png -------------------------------------------------------------------------------- /day-25/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-25/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-25/src/components/Timeline/ActivityItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './Timeline.css' 3 | 4 | export class ActivityItem extends React.Component { 5 | render() { 6 | const { activity } = this.props; 7 | 8 | return ( 9 |
10 |
11 | avatar 14 | {activity.user.name} 15 |
16 | 17 | 18 | {activity.timestamp} 19 | 20 | 21 |

{activity.text}

22 |
23 | {activity.comments.length} 24 |
25 |
26 | ) 27 | } 28 | } 29 | 30 | export default ActivityItem -------------------------------------------------------------------------------- /day-25/src/components/Timeline/Timeline.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import Header from "./Header"; 4 | import ActivityItem from "./ActivityItem"; 5 | import "./Timeline.css"; 6 | 7 | // Could be fetched from a server 8 | const activities = require("../../data.json"); 9 | 10 | // Don't do it like this. This is for example only 11 | class Timeline extends React.Component { 12 | render() { 13 | return ( 14 |
15 |
16 |
17 |
18 |
19 | 20 | {activities && 21 | activities.map(activity => ( 22 | 23 | ))} 24 |
25 |
26 |
27 | ); 28 | } 29 | } 30 | 31 | export default Timeline; 32 | -------------------------------------------------------------------------------- /day-25/src/components/Timeline/__tests__/Timeline-test-test-utils.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import TestUtils from "react-dom/test-utils"; 3 | 4 | import Timeline from "../Timeline"; 5 | 6 | describe("Timeline", () => { 7 | it("wraps content in a div with .notificationsFrame class", () => { 8 | const wrapper = TestUtils.renderIntoDocument(); 9 | TestUtils.findRenderedDOMComponentWithClass(wrapper, "notificationsFrame"); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /day-25/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import "font-awesome/css/font-awesome.css"; 4 | 5 | import Timeline from "./components/Timeline/Timeline"; 6 | 7 | export const load = () => { 8 | ReactDOM.render(, document.getElementById("root")); 9 | }; 10 | 11 | try { 12 | load(); 13 | } catch (e) { 14 | console.log(e); 15 | } 16 | -------------------------------------------------------------------------------- /day-25/src/setupTests.js: -------------------------------------------------------------------------------- 1 | import { configure } from "enzyme"; 2 | import Adapter from "enzyme-adapter-react-16"; 3 | 4 | configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /day-26/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-26/cover.jpg -------------------------------------------------------------------------------- /day-26/nightwatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_folders": ["tests"], 3 | "output_folder": "reports", 4 | 5 | "selenium": { 6 | "start_process": false, 7 | "server_path": "", 8 | "log_path": "", 9 | "host": "127.0.0.1", 10 | "port": 4444, 11 | "cli_args": { 12 | "webdriver.chrome.driver": "", 13 | "webdriver.ie.driver": "" 14 | } 15 | }, 16 | 17 | "test_settings": { 18 | "default": { 19 | "launch_url": "http://localhost:3000", 20 | "selenium_port": 4444, 21 | "selenium_host": "localhost", 22 | "silent": true, 23 | "screenshots": { 24 | "enabled": false, 25 | "path": "" 26 | }, 27 | "desiredCapabilities": { 28 | "browserName": "chrome", 29 | "javascriptEnabled": true, 30 | "acceptSslCerts": true, 31 | "chromeOptions": { 32 | "w3c": false 33 | } 34 | } 35 | }, 36 | 37 | "chrome": { 38 | "desiredCapabilities": { 39 | "browserName": "chrome", 40 | "javascriptEnabled": true, 41 | "acceptSslCerts": true 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /day-26/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "day-26", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.3.2", 8 | "@testing-library/user-event": "^7.1.2", 9 | "font-awesome": "^4.7.0", 10 | "nightwatch": "^1.3.2", 11 | "react": "^16.12.0", 12 | "react-dom": "^16.12.0", 13 | "react-redux": "^7.1.3", 14 | "react-router-dom": "^5.1.2", 15 | "react-scripts": "3.3.0", 16 | "redux": "^4.0.4" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": "react-app" 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /day-26/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-26/public/favicon.ico -------------------------------------------------------------------------------- /day-26/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | React App 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /day-26/reports/CHROME_57.0.2987.133_MAC_auth-flow.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /day-26/reports/CHROME_79.0.3945.79_Linux_auth-flow.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /day-26/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 | -------------------------------------------------------------------------------- /day-26/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 | -------------------------------------------------------------------------------- /day-26/src/Root.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Provider } from 'react-redux'; 3 | import configureStore from './redux/configureStore'; 4 | import App from './App'; 5 | 6 | export const Root = props => { 7 | const store = configureStore(); 8 | return ( 9 | 10 |
11 | 12 |
13 |
14 | ) 15 | } 16 | 17 | export default Root; -------------------------------------------------------------------------------- /day-26/src/components/Form/Form.js: -------------------------------------------------------------------------------- 1 | import React, { Children as C, Component } from 'react'; 2 | 3 | class Form extends Component { 4 | state = { fields: {} } 5 | 6 | handleChange = (key, value) => { 7 | const fields = { 8 | ...this.state.fields, 9 | [key]: value 10 | } 11 | this.setState({ 12 | fields 13 | }) 14 | } 15 | 16 | handleSubmit = e => { 17 | e.preventDefault() 18 | this.props.onSubmit(this.state.fields) 19 | } 20 | 21 | render() { 22 | return ( 23 |
24 | {C.map(this.props.children, c => React.cloneElement(c, { 25 | ...this.props, 26 | onChange: this.handleChange 27 | }))} 28 | 31 |
32 | ) 33 | } 34 | } 35 | 36 | export default Form -------------------------------------------------------------------------------- /day-26/src/components/Form/Input.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const Input = ({ onChange, name, type, ...rest }) => { 4 | return ( 5 |
6 | onChange(name, e.target.value)} 9 | placeholder={name} /> 10 |
11 | ) 12 | } 13 | 14 | export default Input -------------------------------------------------------------------------------- /day-26/src/components/Nav/Navbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Link 4 | } from 'react-router-dom'; 5 | 6 | export const Navbar = ({ auth, logout, ...rest }) => { 7 | 8 | return ( 9 |
10 | 11 | 12 | Logo 13 | 14 |
15 | { 16 | auth.isLoggedIn ? ( 17 |
18 | Logout 19 |
20 | ) : ( 21 |
22 | Login please 23 |
24 | ) 25 | } 26 | 27 | About 28 | 29 |
30 |
31 | ) 32 | } 33 | 34 | export default Navbar -------------------------------------------------------------------------------- /day-26/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import 'font-awesome/css/font-awesome.css'; 5 | 6 | import Root from './Root'; 7 | 8 | export const load = () => { 9 | ReactDOM.render(, document.getElementById('demo1')); 10 | }; 11 | 12 | try { 13 | load(); 14 | } catch (e) { 15 | console.log(e); 16 | } 17 | -------------------------------------------------------------------------------- /day-26/src/redux/actions/auth.js: -------------------------------------------------------------------------------- 1 | import * as types from '../types'; 2 | 3 | export const tryLogin = ({ username, password }) => { 4 | if (username === 'admin' && password === 'secret') { 5 | return { 6 | type: types.LOGIN_SUCCESS, 7 | payload: { username, password } 8 | } 9 | } else { 10 | return { 11 | type: types.LOGIN_FAILURE, 12 | payload: 'Invalid username or password' 13 | } 14 | } 15 | } 16 | 17 | export const tryLogout = () => ({ 18 | type: types.LOGOUT 19 | }) -------------------------------------------------------------------------------- /day-26/src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore } from 'redux'; 2 | import { rootReducer, initialState } from './reducers'; 3 | 4 | export const configureStore = () => { 5 | const store = createStore( 6 | rootReducer, 7 | initialState, 8 | ) 9 | 10 | return store; 11 | } 12 | 13 | export default configureStore -------------------------------------------------------------------------------- /day-26/src/redux/reducers/auth.js: -------------------------------------------------------------------------------- 1 | import * as types from '../types'; 2 | 3 | export const initialState = { 4 | isLoggedIn: false, 5 | userData: null, 6 | pending: false, 7 | errors: null 8 | }; 9 | 10 | export const reducer = (state = initialState, action) => { 11 | switch (action.type) { 12 | case types.TRY_LOGIN: 13 | return { ...state, pending: true } 14 | case types.LOGIN_SUCCESS: 15 | return { 16 | ...state, 17 | pending: false, 18 | isLoggedIn: true, 19 | userData: action.payload, 20 | errors: null, 21 | } 22 | case types.LOGIN_FAILURE: 23 | return { 24 | ...state, 25 | pending: false, 26 | isLoggedIn: false, 27 | userData: null, 28 | errors: action.payload, 29 | } 30 | case types.LOGOUT: 31 | return { 32 | ...state, pending: false, isLoggedIn: false, userData: null 33 | } 34 | default: 35 | return state; 36 | } 37 | } -------------------------------------------------------------------------------- /day-26/src/redux/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import * as auth from './auth'; 4 | 5 | export const initialState = { 6 | auth: auth.initialState, 7 | } 8 | 9 | export const rootReducer = combineReducers({ 10 | auth: auth.reducer 11 | }) -------------------------------------------------------------------------------- /day-26/src/redux/types.js: -------------------------------------------------------------------------------- 1 | export const TRY_LOGIN = 'AUTH_TRY_LOGIN'; 2 | export const LOGIN_SUCCESS = 'AUTH_LOGIN_SUCCESS'; 3 | export const LOGIN_FAILURE = 'AUTH_LOGIN_FAILURE'; 4 | export const LOGOUT = 'AUTH_LOGOUT'; 5 | -------------------------------------------------------------------------------- /day-26/src/views/About.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const About = (props) => ( 4 |
5 |

About us

6 |
7 | ) 8 | 9 | export default About -------------------------------------------------------------------------------- /day-26/src/views/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const Home = ({ auth }) => ( 4 |
5 |

{auth.isLoggedIn ? "Welcome home!" : "You need to know the secret"}

6 |
7 | ); 8 | 9 | export default Home; 10 | -------------------------------------------------------------------------------- /day-27/config/development.config.env: -------------------------------------------------------------------------------- 1 | TIME_SERVER='https://fullstacktime.herokuapp.com' -------------------------------------------------------------------------------- /day-27/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /day-27/config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /day-27/config/production.config.env: -------------------------------------------------------------------------------- 1 | TIME_SERVER='https://fullstacktime.herokuapp.com' -------------------------------------------------------------------------------- /day-27/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-27/cover.jpg -------------------------------------------------------------------------------- /day-27/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-27/public/favicon.ico -------------------------------------------------------------------------------- /day-27/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-27/public/logo192.png -------------------------------------------------------------------------------- /day-27/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-27/public/logo512.png -------------------------------------------------------------------------------- /day-27/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-27/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-27/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-27/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "@testing-library/react"; 3 | import App from "./containers/Root"; 4 | 5 | test("renders welcom home text", () => { 6 | const { getByText } = render(); 7 | const textElement = getByText(/welcome home/i); 8 | expect(textElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-27/src/containers/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; 4 | 5 | // We'll load our views from the `src/views` 6 | // directory 7 | import Home from "./views/Home/Home"; 8 | import About from "./views/About/About"; 9 | 10 | const App = props => { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /day-27/src/containers/Root.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Provider } from "react-redux"; 3 | import App from "./App"; 4 | import configureStore from "../redux/configureStore"; 5 | 6 | const Root = props => { 7 | const store = configureStore(); 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default Root; 16 | -------------------------------------------------------------------------------- /day-27/src/containers/views/About/About.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const About = () => ( 5 |
6 |

About

7 | Go home 8 |
9 | ); 10 | 11 | export default About; 12 | -------------------------------------------------------------------------------- /day-27/src/containers/views/Home/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | // import { Link } from "react-router-dom"; 3 | import { connect } from "react-redux"; 4 | import { fetchNewTime } from "../../../redux/actionCreators"; 5 | 6 | const mapStateToProps = state => { 7 | return { 8 | currentTime: state.currentTime.currentTime 9 | }; 10 | }; 11 | 12 | const mapDispatchToProps = dispatch => ({ 13 | updateTime: () => dispatch(fetchNewTime()) 14 | }); 15 | 16 | const Home = props => ( 17 |
18 |

Welcome home

19 |

Current time: {props.currentTime}

20 | 21 | {/* Go to about */} 22 |
23 | ); 24 | 25 | export default connect(mapStateToProps, mapDispatchToProps)(Home); 26 | -------------------------------------------------------------------------------- /day-27/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-27/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Root from "./containers/Root"; 4 | import "./index.css"; 5 | 6 | ReactDOM.render(, document.getElementById("root")); 7 | -------------------------------------------------------------------------------- /day-27/src/redux/actionCreators.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | // const host = "https://andthetimeis.com"; 4 | const host = process.env.TIME_SERVER; 5 | export const fetchNewTime = (timezone = "pst", str = "now") => ({ 6 | type: types.FETCH_NEW_TIME, 7 | payload: new Date().toString(), 8 | meta: { 9 | type: "api", 10 | url: host + "/" + timezone + "/" + str + ".json" 11 | } 12 | }); 13 | 14 | export const login = user => ({ 15 | type: types.LOGIN, 16 | payload: user 17 | }); 18 | 19 | export const logout = () => ({ 20 | type: types.LOGOUT 21 | }); 22 | -------------------------------------------------------------------------------- /day-27/src/redux/apiMiddleware.js: -------------------------------------------------------------------------------- 1 | const apiMiddleware = store => next => action => { 2 | if (!action.meta || action.meta.type !== "api") { 3 | return next(action); 4 | } 5 | // This is an api request 6 | 7 | // Find the request URL and compose request options from meta 8 | const { url } = action.meta; 9 | const fetchOptions = Object.assign({}, action.meta); 10 | 11 | // Make the request 12 | fetch(url, fetchOptions) 13 | // convert the response to json 14 | .then(resp => resp.json()) 15 | .then(json => { 16 | if (typeof action.meta.onSuccess === "function") { 17 | action.meta.onSuccess(json); 18 | } 19 | return json; // For the next promise in the chain 20 | }) 21 | .then(json => { 22 | // respond back to the user 23 | // by dispatching the original action without 24 | // the meta object 25 | let newAction = Object.assign({}, action, { 26 | payload: json.dateString 27 | }); 28 | delete newAction.meta; 29 | store.dispatch(newAction); 30 | }); 31 | }; 32 | 33 | export default apiMiddleware; 34 | -------------------------------------------------------------------------------- /day-27/src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from "redux"; 2 | 3 | import { rootReducer, initialState } from "./reducers"; 4 | import loggingMiddleware from "./loggingMiddleware"; 5 | import apiMiddleware from "./apiMiddleware"; 6 | 7 | let middleware = [apiMiddleware]; 8 | 9 | if ("development" === process.env.NODE_ENV) { 10 | middleware.unshift(loggingMiddleware); 11 | } 12 | 13 | export const configureStore = () => { 14 | const store = createStore( 15 | rootReducer, 16 | initialState, 17 | applyMiddleware(...middleware) 18 | ); 19 | return store; 20 | }; 21 | 22 | export default configureStore; 23 | -------------------------------------------------------------------------------- /day-27/src/redux/currentTime.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const initialState = { 4 | currentTime: new Date().toString() 5 | }; 6 | 7 | export const reducer = (state = initialState, action) => { 8 | switch (action.type) { 9 | case types.FETCH_NEW_TIME: 10 | return { ...state, currentTime: action.payload }; 11 | default: 12 | return state; 13 | } 14 | }; 15 | 16 | export default reducer; 17 | -------------------------------------------------------------------------------- /day-27/src/redux/currentUser.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const initialState = { 4 | user: {}, 5 | loggedIn: false 6 | }; 7 | 8 | export const reducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case types.LOGIN: 11 | return { 12 | ...state, 13 | user: action.payload, 14 | loggedIn: true 15 | }; 16 | case types.LOGOUT: 17 | return { 18 | ...state, 19 | user: {}, 20 | loggedIn: false 21 | }; 22 | default: 23 | return state; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /day-27/src/redux/loggingMiddleware.js: -------------------------------------------------------------------------------- 1 | const loggingMiddleware = store => next => action => { 2 | // Our middleware 3 | console.log(`Redux Log:`, action); 4 | // call the next function 5 | next(action); 6 | }; 7 | 8 | export default loggingMiddleware; 9 | -------------------------------------------------------------------------------- /day-27/src/redux/reducers.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from "redux"; 2 | 3 | import * as currentUser from "./currentUser"; 4 | import * as currentTime from "./currentTime"; 5 | 6 | export const rootReducer = combineReducers({ 7 | currentTime: currentTime.reducer, 8 | currentUser: currentUser.reducer 9 | }); 10 | 11 | export const initialState = { 12 | currentTime: currentTime.initialState, 13 | currentUser: currentUser.initialState 14 | }; 15 | 16 | export default rootReducer; 17 | -------------------------------------------------------------------------------- /day-27/src/redux/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_NEW_TIME = "FETCH_NEW_TIME"; 2 | export const LOGIN = "USER_LOGIN"; 3 | export const LOGOUT = "USER_LOGOUT"; 4 | -------------------------------------------------------------------------------- /day-27/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-28/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-28/cover.jpg -------------------------------------------------------------------------------- /day-29/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "10.15.0" 4 | before_deploy: 5 | - npm run build 6 | deploy: 7 | provider: script 8 | skip_cleanup: true 9 | script: sh scripts/deploy.sh 10 | on: 11 | branch: master 12 | -------------------------------------------------------------------------------- /day-29/config/development.config.env: -------------------------------------------------------------------------------- 1 | TIME_SERVER='https://fullstacktime.herokuapp.com' -------------------------------------------------------------------------------- /day-29/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /day-29/config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /day-29/config/production.config.env: -------------------------------------------------------------------------------- 1 | TIME_SERVER='https://fullstacktime.herokuapp.com' -------------------------------------------------------------------------------- /day-29/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-29/cover.jpg -------------------------------------------------------------------------------- /day-29/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-29/public/favicon.ico -------------------------------------------------------------------------------- /day-29/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-29/public/logo192.png -------------------------------------------------------------------------------- /day-29/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-29/public/logo512.png -------------------------------------------------------------------------------- /day-29/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /day-29/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | -------------------------------------------------------------------------------- /day-29/scripts/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | surge -p build --domain https://healthy-pail.surge.sh/ -------------------------------------------------------------------------------- /day-29/scripts/release.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = "test"; 2 | process.env.CI = true; 3 | 4 | var chalk = require("chalk"); 5 | const exec = require("child_process").exec; 6 | 7 | var output = []; 8 | 9 | function runCmd(cmd) { 10 | return new Promise((resolve, reject) => { 11 | const testProcess = exec(cmd, { stdio: [0, 1, 2] }); 12 | testProcess.stdout.on("data", msg => output.push(msg)); 13 | testProcess.stderr.on("data", msg => output.push(msg)); 14 | testProcess.on("close", code => (code === 0 ? resolve() : reject())); 15 | }); 16 | } 17 | 18 | function build() { 19 | console.log(chalk.cyan("Building app")); 20 | return runCmd("npm run build"); 21 | } 22 | 23 | function runTests() { 24 | console.log(chalk.cyan("Running tests...")); 25 | return runCmd("npm test"); 26 | } 27 | 28 | function deploy() { 29 | console.log(chalk.green("Deploying...")); 30 | return runCmd(`sh -c "${__dirname}/deploy.sh"`); 31 | } 32 | 33 | function error() { 34 | console.log(chalk.red("There was an error")); 35 | output.forEach(msg => process.stdout.write(msg)); 36 | } 37 | 38 | build() 39 | .then(runTests) 40 | .then(deploy) 41 | .catch(error); 42 | -------------------------------------------------------------------------------- /day-29/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /day-29/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { render } from "@testing-library/react"; 3 | import App from "./containers/Root"; 4 | 5 | test("renders welcom home text", () => { 6 | const { getByText } = render(); 7 | const textElement = getByText(/welcome home/i); 8 | expect(textElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /day-29/src/containers/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import { BrowserRouter as Router, Route, Switch } from "react-router-dom"; 4 | 5 | // We'll load our views from the `src/views` 6 | // directory 7 | import Home from "./views/Home/Home"; 8 | import About from "./views/About/About"; 9 | 10 | const App = props => { 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | ); 19 | }; 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /day-29/src/containers/Root.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Provider } from "react-redux"; 3 | import App from "./App"; 4 | import configureStore from "../redux/configureStore"; 5 | 6 | const Root = props => { 7 | const store = configureStore(); 8 | return ( 9 | 10 | 11 | 12 | ); 13 | }; 14 | 15 | export default Root; 16 | -------------------------------------------------------------------------------- /day-29/src/containers/views/About/About.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | 4 | const About = () => ( 5 |
6 |

About

7 | Go home 8 |
9 | ); 10 | 11 | export default About; 12 | -------------------------------------------------------------------------------- /day-29/src/containers/views/Home/Home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | // import { Link } from "react-router-dom"; 3 | import { connect } from "react-redux"; 4 | import { fetchNewTime } from "../../../redux/actionCreators"; 5 | 6 | const mapStateToProps = state => { 7 | return { 8 | currentTime: state.currentTime.currentTime 9 | }; 10 | }; 11 | 12 | const mapDispatchToProps = dispatch => ({ 13 | updateTime: () => dispatch(fetchNewTime()) 14 | }); 15 | 16 | const Home = props => ( 17 |
18 |

Welcome home

19 |

Current time: {props.currentTime}

20 | 21 | {/* Go to about */} 22 |
23 | ); 24 | 25 | export default connect(mapStateToProps, mapDispatchToProps)(Home); 26 | -------------------------------------------------------------------------------- /day-29/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /day-29/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import Root from "./containers/Root"; 4 | import "./index.css"; 5 | 6 | ReactDOM.render(, document.getElementById("root")); 7 | -------------------------------------------------------------------------------- /day-29/src/redux/actionCreators.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | // const host = "https://andthetimeis.com"; 4 | const host = process.env.TIME_SERVER; 5 | export const fetchNewTime = (timezone = "pst", str = "now") => ({ 6 | type: types.FETCH_NEW_TIME, 7 | payload: new Date().toString(), 8 | meta: { 9 | type: "api", 10 | url: host + "/" + timezone + "/" + str + ".json" 11 | } 12 | }); 13 | 14 | export const login = user => ({ 15 | type: types.LOGIN, 16 | payload: user 17 | }); 18 | 19 | export const logout = () => ({ 20 | type: types.LOGOUT 21 | }); 22 | -------------------------------------------------------------------------------- /day-29/src/redux/apiMiddleware.js: -------------------------------------------------------------------------------- 1 | const apiMiddleware = store => next => action => { 2 | if (!action.meta || action.meta.type !== "api") { 3 | return next(action); 4 | } 5 | // This is an api request 6 | 7 | // Find the request URL and compose request options from meta 8 | const { url } = action.meta; 9 | const fetchOptions = Object.assign({}, action.meta); 10 | 11 | // Make the request 12 | fetch(url, fetchOptions) 13 | // convert the response to json 14 | .then(resp => resp.json()) 15 | .then(json => { 16 | if (typeof action.meta.onSuccess === "function") { 17 | action.meta.onSuccess(json); 18 | } 19 | return json; // For the next promise in the chain 20 | }) 21 | .then(json => { 22 | // respond back to the user 23 | // by dispatching the original action without 24 | // the meta object 25 | let newAction = Object.assign({}, action, { 26 | payload: json.dateString 27 | }); 28 | delete newAction.meta; 29 | store.dispatch(newAction); 30 | }); 31 | }; 32 | 33 | export default apiMiddleware; 34 | -------------------------------------------------------------------------------- /day-29/src/redux/configureStore.js: -------------------------------------------------------------------------------- 1 | import { createStore, applyMiddleware } from "redux"; 2 | 3 | import { rootReducer, initialState } from "./reducers"; 4 | import loggingMiddleware from "./loggingMiddleware"; 5 | import apiMiddleware from "./apiMiddleware"; 6 | 7 | let middleware = [apiMiddleware]; 8 | 9 | if ("development" === process.env.NODE_ENV) { 10 | middleware.unshift(loggingMiddleware); 11 | } 12 | 13 | export const configureStore = () => { 14 | const store = createStore( 15 | rootReducer, 16 | initialState, 17 | applyMiddleware(...middleware) 18 | ); 19 | return store; 20 | }; 21 | 22 | export default configureStore; 23 | -------------------------------------------------------------------------------- /day-29/src/redux/currentTime.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const initialState = { 4 | currentTime: new Date().toString() 5 | }; 6 | 7 | export const reducer = (state = initialState, action) => { 8 | switch (action.type) { 9 | case types.FETCH_NEW_TIME: 10 | return { ...state, currentTime: action.payload }; 11 | default: 12 | return state; 13 | } 14 | }; 15 | 16 | export default reducer; 17 | -------------------------------------------------------------------------------- /day-29/src/redux/currentUser.js: -------------------------------------------------------------------------------- 1 | import * as types from "./types"; 2 | 3 | export const initialState = { 4 | user: {}, 5 | loggedIn: false 6 | }; 7 | 8 | export const reducer = (state = initialState, action) => { 9 | switch (action.type) { 10 | case types.LOGIN: 11 | return { 12 | ...state, 13 | user: action.payload, 14 | loggedIn: true 15 | }; 16 | case types.LOGOUT: 17 | return { 18 | ...state, 19 | user: {}, 20 | loggedIn: false 21 | }; 22 | default: 23 | return state; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /day-29/src/redux/loggingMiddleware.js: -------------------------------------------------------------------------------- 1 | const loggingMiddleware = store => next => action => { 2 | // Our middleware 3 | console.log(`Redux Log:`, action); 4 | // call the next function 5 | next(action); 6 | }; 7 | 8 | export default loggingMiddleware; 9 | -------------------------------------------------------------------------------- /day-29/src/redux/reducers.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from "redux"; 2 | 3 | import * as currentUser from "./currentUser"; 4 | import * as currentTime from "./currentTime"; 5 | 6 | export const rootReducer = combineReducers({ 7 | currentTime: currentTime.reducer, 8 | currentUser: currentUser.reducer 9 | }); 10 | 11 | export const initialState = { 12 | currentTime: currentTime.initialState, 13 | currentUser: currentUser.initialState 14 | }; 15 | 16 | export default rootReducer; 17 | -------------------------------------------------------------------------------- /day-29/src/redux/types.js: -------------------------------------------------------------------------------- 1 | export const FETCH_NEW_TIME = "FETCH_NEW_TIME"; 2 | export const LOGIN = "USER_LOGIN"; 3 | export const LOGOUT = "USER_LOGOUT"; 4 | -------------------------------------------------------------------------------- /day-29/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /day-30/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/day-30/cover.jpg -------------------------------------------------------------------------------- /images/04/breakdown-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/04/breakdown-2.jpg -------------------------------------------------------------------------------- /images/04/breakdown-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/04/breakdown-2.png -------------------------------------------------------------------------------- /images/04/breakdown.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/04/breakdown.jpg -------------------------------------------------------------------------------- /images/04/breakdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/04/breakdown.png -------------------------------------------------------------------------------- /images/04/part4.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/04/part4.sketch -------------------------------------------------------------------------------- /images/12/app.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/app.jpg -------------------------------------------------------------------------------- /images/12/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/app.png -------------------------------------------------------------------------------- /images/12/build.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/build.jpg -------------------------------------------------------------------------------- /images/12/build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/build.png -------------------------------------------------------------------------------- /images/12/chrome-start.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/chrome-start.jpg -------------------------------------------------------------------------------- /images/12/chrome-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/chrome-start.png -------------------------------------------------------------------------------- /images/12/create-app.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/create-app.jpg -------------------------------------------------------------------------------- /images/12/create-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/create-app.png -------------------------------------------------------------------------------- /images/12/index-html.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/index-html.jpg -------------------------------------------------------------------------------- /images/12/index-html.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/index-html.png -------------------------------------------------------------------------------- /images/12/install-create-react-app.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/install-create-react-app.jpg -------------------------------------------------------------------------------- /images/12/install-create-react-app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/install-create-react-app.png -------------------------------------------------------------------------------- /images/12/npm-start.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/npm-start.jpg -------------------------------------------------------------------------------- /images/12/npm-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/npm-start.png -------------------------------------------------------------------------------- /images/12/tree.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/tree.jpg -------------------------------------------------------------------------------- /images/12/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/12/tree.png -------------------------------------------------------------------------------- /images/13/children-map.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/13/children-map.jpg -------------------------------------------------------------------------------- /images/13/children-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/13/children-map.png -------------------------------------------------------------------------------- /images/13/run-no-key.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/13/run-no-key.jpg -------------------------------------------------------------------------------- /images/13/run-no-key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/13/run-no-key.png -------------------------------------------------------------------------------- /images/14/install-fetch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/14/install-fetch.jpg -------------------------------------------------------------------------------- /images/14/install-fetch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/14/install-fetch.png -------------------------------------------------------------------------------- /images/17/install-react-router.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/17/install-react-router.jpg -------------------------------------------------------------------------------- /images/17/install-react-router.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/17/install-react-router.png -------------------------------------------------------------------------------- /images/19/home-time.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/home-time.jpg -------------------------------------------------------------------------------- /images/19/home-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/home-time.png -------------------------------------------------------------------------------- /images/19/install-redux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/install-redux.jpg -------------------------------------------------------------------------------- /images/19/install-redux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/install-redux.png -------------------------------------------------------------------------------- /images/19/no-reducer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/no-reducer.jpg -------------------------------------------------------------------------------- /images/19/no-reducer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/no-reducer.png -------------------------------------------------------------------------------- /images/19/structure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/structure.jpg -------------------------------------------------------------------------------- /images/19/structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/19/structure.png -------------------------------------------------------------------------------- /images/20/home-time.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/20/home-time.jpg -------------------------------------------------------------------------------- /images/20/home-time.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/20/home-time.png -------------------------------------------------------------------------------- /images/20/login-logout.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/20/login-logout.gif -------------------------------------------------------------------------------- /images/23/first-tests.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/23/first-tests.jpg -------------------------------------------------------------------------------- /images/23/first-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/23/first-tests.png -------------------------------------------------------------------------------- /images/23/second-tests.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/23/second-tests.jpg -------------------------------------------------------------------------------- /images/23/second-tests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/23/second-tests.png -------------------------------------------------------------------------------- /images/24/failing-test-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/failing-test-1.jpg -------------------------------------------------------------------------------- /images/24/failing-test-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/failing-test-1.png -------------------------------------------------------------------------------- /images/24/failing-test-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/failing-test-2.jpg -------------------------------------------------------------------------------- /images/24/failing-test-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/failing-test-2.png -------------------------------------------------------------------------------- /images/24/navbar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/navbar.jpg -------------------------------------------------------------------------------- /images/24/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/navbar.png -------------------------------------------------------------------------------- /images/24/passing-test-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/passing-test-1.jpg -------------------------------------------------------------------------------- /images/24/passing-test-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/passing-test-1.png -------------------------------------------------------------------------------- /images/24/passing-test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/24/passing-test.png -------------------------------------------------------------------------------- /images/25/enzyme-test-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/25/enzyme-test-1.jpg -------------------------------------------------------------------------------- /images/25/enzyme-test-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/25/enzyme-test-1.png -------------------------------------------------------------------------------- /images/25/enzyme-test-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/25/enzyme-test-2.jpg -------------------------------------------------------------------------------- /images/25/enzyme-test-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/25/enzyme-test-2.png -------------------------------------------------------------------------------- /images/25/enzyme-test-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/25/enzyme-test-3.jpg -------------------------------------------------------------------------------- /images/25/enzyme-test-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/25/enzyme-test-3.png -------------------------------------------------------------------------------- /images/26/nightwatch-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/nightwatch-1.jpg -------------------------------------------------------------------------------- /images/26/nightwatch-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/nightwatch-1.png -------------------------------------------------------------------------------- /images/26/nightwatch-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/nightwatch-2.jpg -------------------------------------------------------------------------------- /images/26/nightwatch-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/nightwatch-2.png -------------------------------------------------------------------------------- /images/26/nightwatch-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/nightwatch-3.jpg -------------------------------------------------------------------------------- /images/26/nightwatch-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/nightwatch-3.png -------------------------------------------------------------------------------- /images/26/npm-start.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/npm-start.jpg -------------------------------------------------------------------------------- /images/26/npm-start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/npm-start.png -------------------------------------------------------------------------------- /images/26/selenium-server.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/selenium-server.jpg -------------------------------------------------------------------------------- /images/26/selenium-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/26/selenium-server.png -------------------------------------------------------------------------------- /images/28/bitballoon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/bitballoon.jpg -------------------------------------------------------------------------------- /images/28/bitballoon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/bitballoon.png -------------------------------------------------------------------------------- /images/28/gh-pages.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/gh-pages.jpg -------------------------------------------------------------------------------- /images/28/gh-pages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/gh-pages.png -------------------------------------------------------------------------------- /images/28/git-branch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/git-branch.jpg -------------------------------------------------------------------------------- /images/28/git-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/git-branch.png -------------------------------------------------------------------------------- /images/28/github-pages.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/github-pages.jpg -------------------------------------------------------------------------------- /images/28/github-pages.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/github-pages.png -------------------------------------------------------------------------------- /images/28/github-repo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/github-repo.jpg -------------------------------------------------------------------------------- /images/28/github-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/github-repo.png -------------------------------------------------------------------------------- /images/28/github-url.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/github-url.jpg -------------------------------------------------------------------------------- /images/28/github-url.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/github-url.png -------------------------------------------------------------------------------- /images/28/heroku-create.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-create.jpg -------------------------------------------------------------------------------- /images/28/heroku-create.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-create.png -------------------------------------------------------------------------------- /images/28/heroku-deploy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-deploy.jpg -------------------------------------------------------------------------------- /images/28/heroku-deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-deploy.png -------------------------------------------------------------------------------- /images/28/heroku-login.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-login.jpg -------------------------------------------------------------------------------- /images/28/heroku-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-login.png -------------------------------------------------------------------------------- /images/28/heroku-plugin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-plugin.jpg -------------------------------------------------------------------------------- /images/28/heroku-plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-plugin.png -------------------------------------------------------------------------------- /images/28/heroku-static-init.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-static-init.jpg -------------------------------------------------------------------------------- /images/28/heroku-static-init.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku-static-init.png -------------------------------------------------------------------------------- /images/28/heroku.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku.jpg -------------------------------------------------------------------------------- /images/28/heroku.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/heroku.png -------------------------------------------------------------------------------- /images/28/npm-build.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/npm-build.jpg -------------------------------------------------------------------------------- /images/28/npm-build.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/npm-build.png -------------------------------------------------------------------------------- /images/28/pancake.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/pancake.jpg -------------------------------------------------------------------------------- /images/28/pancake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/pancake.png -------------------------------------------------------------------------------- /images/28/s3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/s3.jpg -------------------------------------------------------------------------------- /images/28/s3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/s3.png -------------------------------------------------------------------------------- /images/28/surge-deploy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/surge-deploy.jpg -------------------------------------------------------------------------------- /images/28/surge-deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/surge-deploy.png -------------------------------------------------------------------------------- /images/28/surge.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/surge.jpg -------------------------------------------------------------------------------- /images/28/surge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/28/surge.png -------------------------------------------------------------------------------- /images/29/deploy-fail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/deploy-fail.jpg -------------------------------------------------------------------------------- /images/29/deploy-fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/deploy-fail.png -------------------------------------------------------------------------------- /images/29/deploy-script.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/deploy-script.jpg -------------------------------------------------------------------------------- /images/29/deploy-script.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/deploy-script.png -------------------------------------------------------------------------------- /images/29/travis-activate-repo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-activate-repo.jpg -------------------------------------------------------------------------------- /images/29/travis-activate-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-activate-repo.png -------------------------------------------------------------------------------- /images/29/travis-output.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-output.jpg -------------------------------------------------------------------------------- /images/29/travis-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-output.png -------------------------------------------------------------------------------- /images/29/travis-select-repo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-select-repo.jpg -------------------------------------------------------------------------------- /images/29/travis-select-repo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-select-repo.png -------------------------------------------------------------------------------- /images/29/travis-setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-setup.jpg -------------------------------------------------------------------------------- /images/29/travis-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/29/travis-setup.png -------------------------------------------------------------------------------- /images/headings/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/1.jpg -------------------------------------------------------------------------------- /images/headings/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/10.jpg -------------------------------------------------------------------------------- /images/headings/10_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/10_wide.jpg -------------------------------------------------------------------------------- /images/headings/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/11.jpg -------------------------------------------------------------------------------- /images/headings/11_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/11_wide.jpg -------------------------------------------------------------------------------- /images/headings/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/12.jpg -------------------------------------------------------------------------------- /images/headings/12_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/12_wide.jpg -------------------------------------------------------------------------------- /images/headings/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/13.jpg -------------------------------------------------------------------------------- /images/headings/13_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/13_wide.jpg -------------------------------------------------------------------------------- /images/headings/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/14.jpg -------------------------------------------------------------------------------- /images/headings/14_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/14_wide.jpg -------------------------------------------------------------------------------- /images/headings/15.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/15.jpg -------------------------------------------------------------------------------- /images/headings/15_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/15_wide.jpg -------------------------------------------------------------------------------- /images/headings/16.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/16.jpg -------------------------------------------------------------------------------- /images/headings/16_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/16_wide.jpg -------------------------------------------------------------------------------- /images/headings/17.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/17.jpg -------------------------------------------------------------------------------- /images/headings/17_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/17_wide.jpg -------------------------------------------------------------------------------- /images/headings/18.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/18.jpg -------------------------------------------------------------------------------- /images/headings/18_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/18_wide.jpg -------------------------------------------------------------------------------- /images/headings/19.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/19.jpg -------------------------------------------------------------------------------- /images/headings/19_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/19_wide.jpg -------------------------------------------------------------------------------- /images/headings/1_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/1_wide.jpg -------------------------------------------------------------------------------- /images/headings/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/2.jpg -------------------------------------------------------------------------------- /images/headings/20.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/20.jpg -------------------------------------------------------------------------------- /images/headings/20_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/20_wide.jpg -------------------------------------------------------------------------------- /images/headings/21.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/21.jpg -------------------------------------------------------------------------------- /images/headings/21_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/21_wide.jpg -------------------------------------------------------------------------------- /images/headings/22.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/22.jpg -------------------------------------------------------------------------------- /images/headings/22_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/22_wide.jpg -------------------------------------------------------------------------------- /images/headings/23.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/23.jpg -------------------------------------------------------------------------------- /images/headings/23_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/23_wide.jpg -------------------------------------------------------------------------------- /images/headings/24.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/24.jpg -------------------------------------------------------------------------------- /images/headings/24_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/24_wide.jpg -------------------------------------------------------------------------------- /images/headings/25.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/25.jpg -------------------------------------------------------------------------------- /images/headings/25_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/25_wide.jpg -------------------------------------------------------------------------------- /images/headings/26.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/26.jpg -------------------------------------------------------------------------------- /images/headings/26_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/26_wide.jpg -------------------------------------------------------------------------------- /images/headings/27.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/27.jpg -------------------------------------------------------------------------------- /images/headings/27_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/27_wide.jpg -------------------------------------------------------------------------------- /images/headings/28.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/28.jpg -------------------------------------------------------------------------------- /images/headings/28_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/28_wide.jpg -------------------------------------------------------------------------------- /images/headings/29.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/29.jpg -------------------------------------------------------------------------------- /images/headings/29_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/29_wide.jpg -------------------------------------------------------------------------------- /images/headings/2_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/2_wide.jpg -------------------------------------------------------------------------------- /images/headings/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/3.jpg -------------------------------------------------------------------------------- /images/headings/30.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/30.jpg -------------------------------------------------------------------------------- /images/headings/30_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/30_wide.jpg -------------------------------------------------------------------------------- /images/headings/3_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/3_wide.jpg -------------------------------------------------------------------------------- /images/headings/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/4.jpg -------------------------------------------------------------------------------- /images/headings/4_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/4_wide.jpg -------------------------------------------------------------------------------- /images/headings/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/5.jpg -------------------------------------------------------------------------------- /images/headings/5_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/5_wide.jpg -------------------------------------------------------------------------------- /images/headings/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/6.jpg -------------------------------------------------------------------------------- /images/headings/6_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/6_wide.jpg -------------------------------------------------------------------------------- /images/headings/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/7.jpg -------------------------------------------------------------------------------- /images/headings/7_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/7_wide.jpg -------------------------------------------------------------------------------- /images/headings/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/8.jpg -------------------------------------------------------------------------------- /images/headings/8_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/8_wide.jpg -------------------------------------------------------------------------------- /images/headings/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/9.jpg -------------------------------------------------------------------------------- /images/headings/9_wide.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/headings/9_wide.jpg -------------------------------------------------------------------------------- /images/readme/30-days-of-react-book-cover-2-as-book-220.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/readme/30-days-of-react-book-cover-2-as-book-220.png -------------------------------------------------------------------------------- /images/readme/download-the-pdf-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/readme/download-the-pdf-button.png -------------------------------------------------------------------------------- /images/readme/fullstack-react-hero-book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fullstackreact/30-days-of-react/91579483d2b69a33e7a727b49e24ae61a1ef6882/images/readme/fullstack-react-hero-book.png -------------------------------------------------------------------------------- /internal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "thirty-days-of-react-internal", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "bluebird": "^3.5.1", 13 | "glob": "^7.1.3", 14 | "gray-matter": "^4.0.1", 15 | "lodash": "^4.17.10", 16 | "sharp": "^0.20.7", 17 | "yargs": "^12.0.1" 18 | } 19 | } 20 | --------------------------------------------------------------------------------