layout: true class: title name: title ??? --- layout: true class: content name: content --- layout: true class: content, level-1 name: level-1 --- layout: true class: content, level-2 name: level-2 --- layout: true class: content, level-3 name: level-3 --- layout: true class: image name: image --- layout: true class: bg-cover, image name: full-screen --- layout: true class: double-wide name: double-wide --- layout: true class: double-stack name: double-stack --- layout: true class: code name: code --- layout: true class: title, conversation name: conversation --- layout: true class: title, inverse name: about-title --- layout: true class: title, module, inverse name: module-title --- layout: true template: level-1 name: module --- layout: true template: level-2 name: module-section --- layout: true class: title, module, inverse name: exercise --- layout: true name: cover-art template: title background-image: url(images/title.jpg) class: bg-cover, inverse, cover-art, no-footer ??? --- layout: false--- template: cover-art # Building Your First React App .about[ ## Steven Hicks ### [@pepopowitz](https://twitter.com/pepopowitz)
### steven.j.hicks@gmail.com
### [stevenhicks.me/your-first-react-app](https://stevenhicks.me/your-first-react-app)
] .while-waiting[ ## While we're waiting: ### [stevenhicks.me/your-first-react-app-setup](https://stevenhicks.me/your-first-react-app-setup) ] ??? title image - https://unsplash.com/photos/tjX_sniNzgQ **Contact Info** **Thanks:** * conference * organizers * sponsors * you! timekillers: * where from? * stickers! * favorite talks * favorite speakers * poll about intro * stand up & stretch * high fives --- template: module-title layout: false # Setup --- template: module layout: true # Setup --- ## [stevenhicks.me/your-first-react-app-setup](https://stevenhicks.me/your-first-react-app-setup) ??? intro & setup: 0:00 - 0:?? [timing] git, node, npm, & repo If you **cloned before yesterday** - pull latest! If **not set up**, do this while I talk! (point out url) _If lots didn't do it:_ We'll take 5 minutes to do this now. I'll walk around and help where I can, but please don't hesitate to ask your neighbors if you're having problems. TIMEBOXED TO 5 MINUTES. --- template: module-title layout: false # About --- layout: true template: module name: about-section # About --- ## Me --- template: module-section # About ## Me ### Steven Hicks --- layout: true template: level-3 # About ## Me ### Steven Hicks --- .profile.bio[ ![Me](images/steve-by-olivia-square.jpg) ![Me](images/steve-by-lila-square.jpg) ] ??? I am standing right in front of you so you can tell what I look like But on the left is what my 8 year old daughter Olivia thinks I look like On the right is what my 10 year old daughter Lila thinks I look like and if you think this is just an excuse to talk about my kids and show you their artwork You are correct. --- layout: false class: artsy, no-footer, bg-cover background-image: url('images/artsy.svg') ??? Senior Engineer our mission is to expand the art market, and we're doing that with a platform for collecting and discovering art. --- layout: false template: about-section ## This Workshop --- layout: true template: level-2 name: about # About ## This Workshop --- ### Me: Talk ### You: Exercise ### Me: Recap ??? 17 exercises --- ### Goal: Survey React Landscape ??? because you're going to need more than react to build an app I want you to be prepared to build your next app. --- ### Instructions: README.md --- ### 👉: Specific Task --- ### Answers: SOLUTIONS.md ??? linked from README -- ### Answers: ./complete --- class: no-footer .col.col-10[ ![](images/this-app-1.png) ] ??? view our kitten friends --- class: no-footer .col.col-10[ ![](images/this-app-2.png) ] ??? change theme --- class: no-footer .col.col-10[ ![](images/this-app-3.png) ] ??? details about a kitten --- class: schedule ### Schedule - .highlight[8:00 - ???] Setup, Intro, Modern JavaScript, JSX, React Components, Composition, CSS, Routing - .highlight[??? - ???] Lunch - .highlight[??? - 3:00] State Management, Loading Data, Legacy Components, Testing ??? Now is your chance to break! --- class: collaborative ### Collaborative -- - You + me -- - You + your neighbor ??? Teaching is one of the best ways to learn (meet neighbors comes later) --- ### "Done" Indicator #### Post-it on the back of your laptop --- ### Feedback #### Green = Good; Yellow = Okay; Pink = Bad -- #### Comments Welcome! ??? Q's: How did you like the format? Amount & depth of content? --- template: about-section ## You ??? React devs? JavaScript/UI devs? What UI tools are they using? Angular? Ember? jQuery? --- layout: true template: level-2 # About ## You --- ### Meet your neighbors! -- - Name - Where you're from - What you do - What you're excited about --- template: module-title layout: false # History ??? I've been working on front-end web apps for 20 years I've built them with many different kinds of JavaScript tools --- layout: true template: module name: history-section # History --- ## Plain JavaScript -- - 👎 Hard to write - 👎 Hard to scale ??? Hard to scale **the codebase** If you got it to work, you shipped it. --- ## jQuery -- - 👍 Easy to write - 👎 Hard to scale --- ## MVC/MVVM ??? Angular 1, Knockout, Backbone, ... -- - 👍 Easy to scale - 👎 Hard to write ??? sometimes... --- ## MVC/MVVM - 👍 Easy to write - 👎 Hard to scale ??? other times. Regardless, an improvement! --- ## React ??? My favorite way to build a web app -- - 👍 Easy to write - 👍 Easy to scale ??? When we talk about tools, it's helpful to know what problem they solve. That's the problem react solves... --- template: module-title layout: false # React ??? There are a bunch of things that react is... the most significant one, for me, is... --- layout: true template: module name: react-section # React Is --- ## Simplicity ## + ## Scalability ??? React makes it easy to scale simple, understandable code to a large app. simplicity: hope you can experience today --- template: module-section # React Is ## Scalable ### 30,000 -- #### The number of React components in Facebook's codebase .footnote[ [Dan Abramov](https://medium.com/@dan_abramov/hey-thanks-for-feedback-bf9502689ca4) ] ??? scalability: number of components in Facebook's codebase source: https://medium.com/@dan_abramov/hey-thanks-for-feedback-bf9502689ca4 --- layout: true template: react-section --- > A JavaScript library for building user interfaces .footnote[ https://reactjs.org/ ] ??? from their site dumb - of course that's what it is but there's meaning here - it is ONLY a UI framework --- ## The V in MVC ??? And nothing more (maybe the C) --- layout: true template: module-section name: react-is-v-in-mvc # React Is ## The V in MVC --- ### Angular : monolith :: ### React : microlibraries --- > Choosing between Angular and React is like choosing between buying an off-the-shelf computer and building your own with off-the-shelf parts. .footnote[ [Cory House](https://medium.freecodecamp.com/angular-2-versus-react-there-will-be-blood-66595faafd51) ] --- template: react-section layout: true --- ## Declarative ??? What does that mean? Well, it means we write code that says **WHAT** to display **not HOW** to display it --- layout: true template: module-section name: react-is-declarative # React Is ## Declarative --- ### How do you get to my house? --- class: bg-contain, hide-footer background-image: url('images/drawings/imperative.jpg') ### How do you get to my house? ??? imperative --- class: bg-contain, hide-footer background-image: url('images/drawings/declarative.jpg') ### How do you get to my house? ??? declarative - abstracts the imperative Obviously some code, at some point, has to be written on HOW to display --- ### Imperative code is abstracted ### so that we can call it declaratively ??? But we abstract the imperative code So our app can call it declaratively. --- ```javascript var kittensComingToMyParty = []; for (var i = 0; i < kittens.length; i++) { var kitten = kittens[i]; if (kitten.rsvp === true) { kittensComingToMyParty.push(kitten); } } ``` ??? if I wanted to know which kittens were coming to my party, I could write code like this imperative -- ```javascript var kittensComingToMyParty = kittens.filter( kitten => kitten.rsvp === true); ``` ??? ... declarative ... Why do we care about this? --- > Declarative views make your code more predictable and easier to debug. .footnote[ https://facebook.github.io/react/ ] ??? When your code is less worried about HOW to do things, it's less cognitive load on the reader. --- template: react-section layout: true --- ## Component-Based --- template: module-section # React Is ## Component-Based > Build encapsulated components that manage their own state, then compose them to make complex UIs. .footnote[ https://facebook.github.io/react/ ] ??? (read) ... We'll talk more about components in a bit ... but before we do, we need to take a step backwards from even React Let's talk about JavaScript. --- template: module-title layout: false # JavaScript ??? There are some JS tools we're going to be using today that you might have heard of --- layout: true template: module name: javascript-section # JavaScript --- ## 1. npm ### Node Package Manager ??? problem solved: makes it easier to **manage dependencies** --- layout: true template: module-section # JavaScript ## npm --- ??? looking at the history of building web apps --- class: bg-contain background-image: url('images/drawings/dependencies-old-school.jpg') ??? oldest way (1): download a library & put it in a folder --- class: bg-contain background-image: url('images/drawings/dependencies-bower.jpg') ??? old way (2): bower --- class: bg-contain background-image: url('images/drawings/dependencies-npm.jpg') ??? new way (3): npm ... we're going to use npm for a couple things --- class: bg-contain, hide-footer background-image: url('images/drawings/npm-dependencies.jpg') ??? 1. to collect & organize our dependencies --- class: bg-contain, hide-footer background-image: url('images/drawings/npm-scripts.jpg') ??? to use npm, you need a manifest to identify all your dependencies. this is the package.json. A cool thing the package.json also allows you to do is define scripts so 2. we'll **run app & tests**, via npm scripts --- class: bg-contain, hide-footer background-image: url('images/drawings/npm-chart.jpg') ??? rolling 28 day downloads - over 25 million NPM usage is growing at a crazy rate Tons of packages That means the user might have to download a ton of different libraries to their browser to run our app. so... --- layout: true template: javascript-section --- ## 2. webpack ??? problem solved: large javascript downloads --- template: module-section class: bg-contain, hide-footer background-image: url('images/drawings/webpack.jpg') # JavaScript ## webpack ??? removes unused code compresses & minifies our bundle good development experience --- layout: true template: javascript-section --- ## 3. ES-modern ### ES6+, ES2015+, ... ??? problem solved: JavaScript for the web didn't change at all between 1999 and 2009. It changed very little from 1999 to 2015. But we've learned a lot about programming languages since 1999. Especially the importance of readability & developer experience. We're now getting new versions of JavaScript via the EcmaScript specification And it's bringing lots of developer-friendly changes. ... Let's look at some of those changes, because there are some that impact the way we can write React code. --- template: exercise layout: false # Exercise 1 ## Modern JavaScript: Modules ??? git checkout master git pull npm run test-exercise-1 --- template: module-title layout: false # Components --- layout: true template: module name: components-section # Components --- ## The "Component" Mindset ??? Components are React's biggest contribution to web dev It's a mindset shift When we were doing MVC/MVVM, we used to think in terms of "controllers" and "views" We did this because of the principle of "separation of concerns" But React says controllers & views are the same concern - a component. --- template: module-section layout: true # Components ## The "Component" Mindset --- class: bg-contain, hide-footer background-image: url('images/drawings/twitter-1.jpg') ??? twitter so instead of this page having a controller & a view, --- class: bg-contain, hide-footer background-image: url('images/drawings/twitter-2.jpg') ??? it really has a handful of components building blocks and each of those components is a concern --- class: bg-contain, hide-footer background-image: url('images/drawings/twitter-3.jpg') ??? and it goes further than that - each of those components is composed... --- class: bg-contain, hide-footer background-image: url('images/drawings/twitter-4.jpg') ??? of more components --- template: exercise layout: false # Exercise 2 ## Identifying Components --- template: level-3 layout: true # Components ## Exercise 2 ### Identify Components --- #### Draw the boundaries of individual components on each page --- template: exercise class: bg-contain, no-footer background-image: url('images/drawings/component-exercise-1.jpg') --- template: exercise class: bg-contain, no-footer background-image: url('images/drawings/component-exercise-2.jpg') --- template: components-section ## Suggestions --- template: module-section layout: true # Components ## Suggestions --- ### Favor small components ??? The **deconstruction** of UI's into small components is crucial to successful React development. --- ### Components are more about isolation than reuse ??? It's easy to think we are doing this to make reuse easier But it's really more about isolation --- class: bg-contain background-image: url('images/drawings/building-blocks.jpg') ??? Components are like building blocks. Smaller ones that do fewer things are easier to understand And easier to assemble (so they aid reuse). --- template: module-title layout: false # Components + React --- layout: true template: module name: components-react-section # Components + React --- ## Components Are Functions --- template: module-section layout: false # Components + React ## Component Functions ```javascript import React from 'react'; function FriendsList { // ...Details about this component } ``` ??? - import react - FriendsList component is a function --- class: no-footer ### Pure Functions > [a component function...] should be pure, meaning that it does not modify component state, it returns the same result each time it’s invoked, and it does not directly interact with the browser. .footnote[ https://reactjs.org/docs/ ] ??? Ideally, these component functions should be pure ... 2 parts to "pure": 1.doesn't modify state 2.returns same value with same args ... let's look at some examples of pure & impure functions to give you clarity on the difference --- template: level-2 layout: true # Components + React ## Pure Functions --- ```javascript function add(a, b) { return a + b; } ``` -- ##### Pure 😊 ??? our example from earlier pure doesn't modify the state of anything returns the same result each time --- ```javascript function now() { return new Date(); } ``` -- ##### Impure 😟 ??? impure it doesn't return the same result each time --- ```jsx function Friend() { this.x = this.x - 1; } ``` -- ##### Impure 😟 ??? impure it modifies the state of the component note: I used the worried face, not sad face cuz impure functions cause you to worry about side-effects & unpredictability --- template: components-react-section ## Inputs --- template: module-section layout: true # Components + React ## Inputs --- > Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen. .footnote[ https://reactjs.org/docs/ ] --- template: level-3 layout: true # Components + React ## Inputs ### props --- class: bg-contain background-image: url('images/drawings/component-f-props.jpg') ??? component = function of props, the result of which is output to browser --- ```jsx function Friend(props) { * console.log(props.name, props.url); } ``` ??? - taking in props --- template: components-react-section layout: false ## Output ??? How do we actually get something on the screen? we know it goes in our function but what actually renders markup? --- template: module-section layout: false # Components + React ## Output ### React.createElement() --- template: level-3 layout: true # Components + React ## Output ### createElement() --- ```jsx function Friend() { return React.createElement('div'); } ``` ??? create a simple element -- ```html
``` ??? emits a div --- ```jsx function Friend() { return React.createElement('button'); } ``` ```html
``` ??? other element types --- ```jsx function Friend() { return React.createElement('div', { id: 'friend-wrapper' }); } ``` ```html
``` ??? - 2nd argument (optional): "props" - props to apply to rendered element - pass as many props as you want --- ```jsx function Friend() { return React.createElement('div', { id: 'friend-wrapper' }, 'Hi!'); } ``` ```html
Hi!
``` ??? - 3rd arg (optional): children - text node, in this example --- ```jsx function Friend(props) { return React.createElement( 'div', { id: 'friend-wrapper'}, * props.name ); } ``` ```html
Potatoes
``` ??? - props as text node! - **Outputs are re-rendered as their inputs change** - React handles this for you! --- ```jsx function Friend(props) { if (props.name === 'Potatoes') { return React.createElement('div', null, 'We`re best friends!'); } return React.createElement('div', null, 'We`re not best friends.'); } ``` ??? since our component is pure javascript we can do things like conditional rendering -- ```html
We`re best friends!
``` ??? - shows when name is Potatoes -- ```html
We`re not best friends.
``` ??? - shows in other cases --- ```jsx function Friend(props) { return React.createElement( 'div', null, React.createElement('h1', null, 'Hello, ' + props.name) ); } ``` ```html
Hello, Potatoes
``` ??? - nest calls to React.createElement - emits nested elements ... you can build an entire React app using React.createElement. but here's the problem with react.createlement. Most of the things we render to a webpage aren't 1 or 2 html elements. --- ```html
Potatoes
4 months
``` ??? They're often more like this - and this is even on the small side. (describe html) ... here's what our createElement statement looks like for this - --- class: no-footer, medium ```jsx function Friend(props) { return React.createElement( 'div', { id: 'friend' }, React.createElement( 'div', { id: 'title' }, React.createElement('h1', null, props.name), React.createElement('h2', null, props.age) ), React.createElement( 'div', { id: 'photo' }, React.createElement( 'a', { href: '/friends/' + props.id, }, React.createElement('img', { src: props.profileImageUrl, alt: props.name, }) ) ) ); } ``` ??? This is not that easy to read I'd even describe it as "barfy" ... this is where another library comes in --- template: module-section layout: false # Components + React ## Output ### JSX --- template: level-3 layout: true # Components + React ## Output ### JSX --- > JSX is an XML-like syntax extension to ECMAScript without any defined semantics. .footnote[ https://facebook.github.io/jsx/ ] ??? It's XML in Javascript ... here's what it looks like --- ```jsx function Friend() { return React.createElement('div'); } ``` ??? as createElement: An example from earlier. -- ```jsx function Friend() { return
; } ``` ??? as jsx: Looks like the markup we want to render! --- ```jsx function Friend(props) { return React.createElement( 'div', null, React.createElement('h1', null, 'Hello, ' + props.name) ); } ``` ??? another example - more complicated -- ```jsx function Friend(props) { return (
Hello, {props.name}
); } ``` ??? {} - you want to evaluate a js expression there ... why would we do this to ourselves? why put xml in javascript? it's like a horror film from 2004. --- #### React.createElement Is Verbose --- class: no-footer, medium ```jsx function Friend(props) { return React.createElement( 'div', { id: 'friend' }, React.createElement( 'div', { id: 'title' }, React.createElement('h1', null, props.name), React.createElement('h2', null, props.age) ), React.createElement( 'div', { id: 'photo' }, React.createElement( 'a', { href: '/friends/' + props.id, }, React.createElement('img', { src: props.profileImageUrl, alt: props.name, }) ) ) ); } ``` ??? remember our most complicated createElement example ? --- ```jsx function Friend(props) { return (
{props.name}
{props.age}
); } ``` ??? --- #### Optional ??? you can build an entire app with createElement we'll use it today because it makes your code much more readable ... who still doesn't like this idea? (poll for separation of concerns) REPEAT THEIR ANSWER!!!! --- #### Separation Of Concerns --- class: bg-contain background-image: url('images/drawings/slicing-horizontal.jpg') ??? React components with JSX look like HTML + JS the instinct is to separate them --- class: no-footer #### Separation Of Technologies > Instead of artificially separating technologies by putting markup and logic in separate files, React separates concerns with loosely coupled units called “components” that contain both. .footnote[ https://reactjs.org/docs/ ] ??? A component's concern is rendering It's that friend or that list of friends --- class: bg-contain background-image: url('images/drawings/slicing-vertical.jpg') ??? And it takes HTML + JS to render them You can think of components changing the way we're slicing the app ... The rub... --- #### Browsers Just Don't Understand ??? So we have to transpile. It is an extra step between our code & the browser. But remember, we're already using webpack to minimize our dependencies from npm --- ```jsx function Friend(props) { return (
{props.name}
{props.age}
); } ``` ??? Does anyone want to guess what this transpiles to? --- class: no-footer, medium ```jsx function Friend(props) { return React.createElement( 'div', { id: 'friend' }, React.createElement( 'div', { id: 'title' }, React.createElement('h1', null, props.name), React.createElement('h2', null, props.age) ), React.createElement( 'div', { id: 'photo' }, React.createElement( 'a', { href: '/friends/' + props.id, }, React.createElement('img', { src: props.profileImageUrl, alt: props.name, }) ) ) ); } ``` --- template: exercise layout: false # Exercises 3 & 4 ## Modern JavaScript: Working With Variables ## JSX Fundamentals ??? - New features to make it easier to work with objects - different things you can do in jsx --- template: module-title layout: false # Components + React + JSX --- layout: true template: module name: components-react-jsx-section # Components + React + JSX --- ## A component can `return` 5\* things ??? can return five things\* (actually more but we're only going to talk about 5) --- template: module-section layout: true # Components + React + JSX ## Can `return` --- ### 1. Element/React Component -- ```jsx function Friend(props) { return ( *
* {props.name} *
); } ``` ??? return a DOM node --- ### 1. Element/React Component ```jsx function Friend(props) { return ( *
); } ``` ??? return another user-defined component. --- ### 2. Array -- ```jsx function Friend(props) { * return [ *
, *
, * ] } ``` ??? Let you return multiple elements it's more valuable than you think this example is not something you'll do a lot of... --- ### 2. Array ```jsx function Friend(props) { * return props.friends.map(friend => *
* ); } ``` ??? but this is! mapping from an array to an array of react components. --- ### 3. Fragment -- ```jsx import React, { Fragment } from 'react'; function Friend(props) { return ( *
*
*
*
); } ``` ??? Nicer syntax than returning an array, if you have multiple items to return Fragment does not render anything to the DOM It used to be that you had to wrap things in a div, instead of a fragment (pollution) --- ### 3. Fragment ```jsx import React from 'react'; function Friend(props) { return ( * <> *
*
* > ); } ``` ??? Shortcut for rendering a fragment - don't need to import Fragment - "empty" tag --- ### 4. String/Number -- ```jsx function Friend(props) { * return props.name; } ``` ??? These are rendered as text nodes in the DOM. --- ### 5. null -- ```jsx function Friend() { * return null; } ``` ??? renders nothing. you could do this, but you won't. .. you WILL do this, though --- ### 5. null ```jsx function Friend(props) { * if (props.isLoading) { * return null; * } return
{props.name}
} ``` ??? early-exit from a component --- template: exercise layout: false # Exercise 5 ## What can a component render? ??? the different types of things a component can render --- template: components-react-jsx-section layout: false ## Common Errors --- template: module-section layout: true # Components + React + JSX ## Common Errors --- ### Component Names Must Be Capitalized .error[ > The tag < friendsList > is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.` > ] --- ### Components Must Return Something .error[ > Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.` > ] --- ### Components Must Return Something ```jsx function Friend(props) {
{props.name}
; } ``` ??? you'll write components like this, many times the problem? --- ### Components Must Return Something ```jsx function Friend(props) { return
{props.name}
; } ``` ??? it's not actually RETURNING the jsx. --- ### Components Must Return Something ```jsx export default function(props) { return
{props.name}
; } ``` ??? another thing you'll do plenty of times what's wrong? that return is returning! --- ### Components Must Return Something ```jsx export default function(props) { * return (
{props.name}
* ); } ``` ??? we need parens on the same line, to tell it not to just terminate that statement. with modern editors this is harder to do now than it was a year ago, but still something to be aware of. --- template: module-title layout: false # Props --- layout: true template: module name: props-section # Props --- class: bg-contain background-image: url('images/drawings/component-f-props.jpg') ??? Our Component Inputs --- ## Should Never Be Modified -- ```jsx function Friend(props) { * props.name = 'Mr. Cat The Mystery Cat'; return
{props.name}
} ``` ??? If a prop needs to be changed... it's probably state (not a prop) --- ## Syntax ??? We've seen in some examples already -- ```jsx *function Friend(props) { if (props.isLoading) { return null; } return
{props.name}
; } ``` ??? `props` arg is passed in and it contains a property for each individual prop --- ## Syntax ```jsx function Friend(props) { * const { isLoading, name } = props; if (isLoading) { return null; } return
{name}
} ``` ??? object destructuring --- ## Syntax ```jsx *function Friend({ isLoading, name }) { if (isLoading) { return null; } return
{name}
} ``` ??? argument destructuring --- ## Default Props ??? specify defaults for props -- ```jsx function FriendProfile({ name, image }) { return
} *FriendProfile.defaultProps = { * image: 'http://placekitten.com/200' *} ``` ??? assign to the function afterward --- ## Default Props ```jsx function FriendProfile( { name, * image = 'http://placekitten.com/200' } ) { return
} ``` ??? with argument destructuring --- ## Children ??? Every component gets a special prop -- ```jsx function Title({ children }) { return
{children}
; } ``` ??? ... example: a Title component Title component gets children passed in -- ```jsx
Hello, friends!
``` ??? ... the children are everything inside of the Title element -- ```html
Hello, friends!
``` ??? ... this is what gets emitted to the DOM note the children being wrapped inside the div ... children prop is really powerful. --- template: module-section layout: true # Props ## Children --- ### Composition ??? allows us to compose our components, instead of inherit them easier to assemble building blocks easier to refactor/change (less brittle than inheritance) --- template: exercise layout: false # Exercise 6 ## Composition & `props.children` ??? building components that aid composition --- template: props-section layout: true --- ## Prop Validation ??? With so many components flying around, nested deeply inside each other... how do we make sure our component is getting the data it needs? --- ## PropTypes --- template: module-section layout: true # Props ## PropTypes --- ### Optional ??? You don't need them to build an app --- ``` npm install --save prop-types ``` ??? Used to be part of React Now an external library --- ```jsx import propTypes from 'prop-types'; function FriendProfile({ name, image }) { return
; } *FriendProfile.propTypes = { * name: propTypes.string.isRequired, * image: propTypes.string.isRequired, *} ``` ??? syntax: append after --- ```js Friends.propTypes = { friends: PropTypes.arrayOf( PropTypes.shape({ id: PropTypes.number.isRequired, name: PropTypes.string.isRequired, }) ).isRequired, }; ``` ??? arrays shapes isRequired --- ### Validate At Run-Time ??? You fire up a browser, view your component, & see an error in the console --- ```js index.js:1446 Warning: Failed prop type: The prop `age` is marked as required in `FriendProfile`, but its value is `undefined`. in FriendProfile (at Exercise.js:10) in Friends (at Exercise.js:5) in Exercise (at App.js:13) in div (at App.js:12) in div (at App.js:7) in App (at exercise-6/index.js:6) ``` ??? This is what the error looks like --- template: props-section layout: false ## Suggestions --- template: module-section layout: true # Props ## Suggestions --- ### Turn off propType validation in production ??? propTypes are a development tool --- template: props-section ## Deeper Learning --- template: module-section layout: true # Props ## Deeper Learning --- ### TypeScript ```jsx *interface FriendProfileProps { * name: string; * image: string; *} *function FriendProfile(props: FriendProfileProps) { const { name, image } = props; return
; } ``` ??? - define interfaces of the required props - ts compiler becomes part of build step - will give you a **compile-time** error if it doesn't get those types - can use for more than react components --- ### Flow ```jsx *type FriendProfileProps = { * name: string; * image: string; *} *function FriendProfile(props: FriendProfileProps) { const { name, image } = props; return
; } ``` ??? - looks similar to ts - also compile-time - better tooling from typescript ... If I were starting a new project, I would use TypeScript. --- template: module-title layout: false # CSS --- layout: true template: module name: css-section # CSS --- ## Styles Go With Components ??? most important thing to know: gone are the days of one massive stylesheet for an entire app with react's focus on components, we want to put our styles with our components. ... A few different approaches. --- ## Method 1: Component CSS Files --- template: module-section layout: false # CSS ## Component CSS Files ```css .friend { color: blueviolet; border-bottom: 1px solid blueviolet; } ``` .footnote[ friend.css ] ```jsx *import './friend.css'; function Friend({ name }) { * return
{name}
}); ``` .footnote[ friend.jsx ] ??? - css file: specific to friend component - friend component imports css file - className refers to class from .css file Note that this works because we're using **webpack with style-loader** (it effectively turns our css into a js object that we can import) --- ## Method 2: CSS Modules ### https://github.com/css-modules/css-modules .css-modules[ ![CSS Modules](images/css-modules-logo.png) ] --- template: module-section layout: true # CSS ## CSS Modules --- class: no-footer ### Why? > - modular and reusable CSS! > - No more conflicts. > - Explicit dependencies. > - No global scope. .footnote[ [CSS Modules](https://github.com/css-modules/css-modules) ] ??? the problems css-modules aims to solve: --- ```css .friend { color: blueviolet; border-bottom: 1px solid blueviolet; } ``` .footnote[ friend.css ] ```jsx *import styles from './friend.css'; function Friend({ name }) { * return
{name}
} ``` .footnote[ friend.jsx ] ??? what it looks like in your code: - css file specific to friend - import into component **as default dep** - reference classname as a property on styles --- ```css .Friend__friend__31BtE { color: blueviolet; border-bottom: 1px solid blueviolet; } ``` .footnote[ CSS ] ```html
Mr. Turtle
``` .footnote[ HTML ] ??? what gets shipped to the browser - name-mangled --- template: css-section ## Method 3: Styled Components ### [styled-components.com](https://www.styled-components.com/) --- template: module-section layout: true # CSS ## Styled Components --- ```jsx import styled from 'styled-components'; const brandColor = 'blueviolet'; const StyledFriend = styled.div` color: ${brandColor}; border-bottom: 1px solid ${brandColor}; `; function Friend({ name }) { return
{name}
; } ``` ??? - import styled - styles are in the component! - tagged template literal to create styled component - styled component in return statement --- ```css .31bte { color: blueviolet; border-bottom: 1px solid blueviolet; } ``` .footnote[ CSS ] ```html
Mr. Turtle
``` .footnote[ HTML ] ??? shipped to the browser --- template: exercise layout: false # Exercise 7 ## CSS: Three Ways To Style --- template: css-section ## Deeper Learning --- template: module-section layout: true # CSS ## Deeper Learning --- class: no-footer ### CSS-in-JS -- - [Styled Components](https://www.styled-components.com) - [Radium](https://github.com/FormidableLabs/radium) - [Emotion](https://github.com/emotion-js/emotion) - [Glamor](https://github.com/threepointone/glamor) - [Glamorous](https://github.com/paypal/glamorous) - [JSS](https://github.com/cssinjs/jss) ??? soooo many ways --- template: css-section ## Suggestions --- template: module-section layout: true # CSS ## Suggestions --- > Find the way that works for you, and do it unapologetically .footnote[ Scott Hanselman ] ??? People who use css-in-js REALLY like it I've never felt like managing CSS scope was a problem But it might depend on what you're building - Component library probably warrants css-in-js --- ### Separation Of Concerns --- template: level-3 layout: false class: bg-contain background-image: url('images/drawings/slicing-vertical.jpg') # CSS ## Suggestions ### Separation Of Concerns --- ### Styling Belongs To Your Components ??? the important thing is that you have component-based css via imported css, imported scss, css modules, css-in-js.... The main takeaway is that styles are not a separate concern from the rest of the component. --- template: module-title layout: false # Routing --- layout: true template: module name: routing-section # Routing --- ## React Router ### https://reacttraining.com/react-router/ ??? ...some things about react router: --- layout: true template: module-section name: react-router-section # Routing ## React Router --- ### Declarative -- ```javascript import { BrowserRouter, Route } from 'react-router-dom'; function App() { return ( *
*
*
*
*
); } ``` ??? - imports - browserrouter wrapper - routes specify which components handle which urls --- ### Routes Are Components ??? Almost everything in react router is a component -- ```jsx import { BrowserRouter, Route } from 'react-router-dom'; function App() { return ( *
*
*
*
*
); } ``` --- ### Routes Are Rendered Dynamically ??? in most SPA frameworks, you define routes up front with React Router, routes are part of the component tree so the routing happens as things are rendering -- ```jsx import { BrowserRouter, Route } from 'react-router-dom'; *function App() { return (
); } ``` ??? ... look - the router/route components are in the return statement It's a subtle difference But it allows you to write declarative routing which is pretty easy to follow. --- ### <BrowserRouter&gt; ```jsx *import { BrowserRouter, Route } from 'react-router-dom'; function App() { return ( *
*
); } ``` ??? key components you'll use: A Router that targets the browser uses the HTML5 history API to keep your UI in sync with the URL. you'll generally put this at the top of your app --- ### <Route&gt; ```jsx *import { BrowserRouter, Route } from 'react-router-dom'; function App() { return (
*
*
*
); } ``` ??? a few key arguments to a Route component --- template: level-3 layout: true # Routing ## React Router ### <Route&gt; --- #### path ```jsx
``` ??? - Which url is covered - can be static -- ```jsx
``` ??? - or can be dynamic, with arguments in it --- #### component ```jsx
``` ??? which component handles this route? --- #### exact ```jsx
``` ??? does the path need to match exactly? without this, the root path would _always_ match. ... That's all it takes to define your routes! The other components you'll use from React-Router are for navigating --- template: react-router-section ### <Link> ```jsx import { Link } from 'react-router-dom'; function FriendInList({ friend }) { return
{friend.name}; } ``` ??? effectively an anchor/href --- template: react-router-section ### <NavLink> ```jsx import { NavLink } from 'react-router-dom'; function FriendInList({ friend }) { return (
Home
Friends
Lists
); } ``` ??? - like a link, but it also sets an "active" class when it is selected. - useful in navigation where you want to identify current page --- template: exercise layout: false # Exercise 8 ## React Router --- template: routing-section ## Suggestions --- template: module-section class: no-footer # Routing ## Suggestions > To get your intuition in line with React Router’s, think about components, not static routes. Think about how to solve the problem with React’s declarative composability because nearly every “React Router question” is probably a “React question”. .footnote[ https://reacttraining.com/react-router/web/guides/philosophy ] --- template: routing-section ## Deeper Learning --- template: module-section layout: true # Routing ## Deeper Learning --- ### Transitions ??? can use to: - block navigation (i.e. not authorized) - animate transitions --- ### Reach Router #### https://reach.tech/router ??? - written by co-author of react router - focused on accessibility --- template: module-title layout: false # State ??? Who has heard things about managing state in react? ... state mgmt in react is a controversial topic. but it has gotten less controversial with more recent releases --- layout: true template: module-section name: state-module-section # State --- layout: true template: module name: state-section # State --- class: bg-contain background-image: url('images/drawings/component-f-props.jpg') ??? this is where we were a component is a function of the props passed into it --- class: bg-contain background-image: url('images/drawings/component-f-props-state.jpg') ??? but that's not the only input to a component a component is a function of props & state ... distinction: - props are passed into a component - state is contained within a component Think about it from a responsibility viewpoint Who should be the source of truth for this data? This component? It's state. Someone else? It's props passed in. --- ## State Is Passed Into Child Components As Props --- class: bg-contain background-image: url('images/drawings/state-turns-into-props.jpg') ??? - top level manages state; - each component down the line passes it to the next --- ## Hooks ??? To manage state, we'll use a new React feature named hooks - v16.8 - new as of ~Feb 2019 --- template: module-section layout: true # State ## Hooks --- > Hooks are functions you can use in a Component to perform **impure actions** from a **pure function**. ??? Remember we said our components are pure functions, and pure functions shouldn't have side-effects, or change state Hooks allow us to do that safely, and in a way that allows React to re-render components when it needs to --- ### `useState` ### `useEffect` ### `useReducer` ### `useMemo` ### ... ??? Examples - manage state - perform side-effects - manage complicated state - memoize some data (another type of state) All begin with "use" - allows React to identify hooks that you create --- template: state-section ## `useState` ??? our focus for state mgmt --- template: module-section layout: true ## `useState` --- ```jsx function FriendCounter() { * const state = useState(99); * const count = state[0]; * const setCount = state[1]; return (
{count}
); } ``` ??? - useState - initial value (99) - get an array back - first item in array = value - second item in array = state modifier ... Why do we get back an array? So we can do this: --- ```jsx function FriendCounter() { * const [count, setCount] = useState(99); return (
{count}
); } ``` ??? - array destructuring - an array so that we can name them whatever we want --- ```jsx function FriendCounter() { * const [count, setCount] = useState(99); return (
{count}
*
setCount(count + 1)} />
); } ``` ??? To use the state modifier, We might add an onClick handler - when executed, calls setCount with the new value - fat-arrow because we pass onClick a _function_ to execute - if we just called setCount() directly, that would happen at render instead of click --- template: exercise layout: false # Exercise 9 ## Managing Component State ??? build a component that uses state to manage which view is being shown --- template: state-section ## Suggestions --- template: state-module-section layout: true name: state-suggestions ## Suggestions --- ### Only call hooks at the top level ??? That means never in a conditional or loop - Order of calls to `useState` matters - Hooks relies on order to keep track of each state prop - there's some magic --- ### Elevate State --- template: level-3 layout: true # State ## Suggestions ### Elevate State --- class: bg-contain background-image: url('images/drawings/state-tree-leaves.jpg') ??? if I've got components down here that need the same state... --- class: bg-contain background-image: url('images/drawings/state-tree-drilling.jpg') ??? I can elevate it to the nearest common ancestor and manage the state there --- template: state-suggestions ### Managing Many State Properties ??? You can call `useState` more than once --- template: level-3 layout: true # State ## Suggestions ### Many State Properties --- ```jsx function FriendForm() { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); // ... } ``` ??? Example: two state props, one for each name --- ```jsx function FriendForm() { const [firstName, setFirstName] = useState(''); const [middleInitial, setMiddleInitial] = useState(''); const [lastName, setLastName] = useState(''); const [nickname, setNickname] = useState(''); const [age, setAge] = useState(0); // ... } ``` ??? But you can see how this can get out of hand, if you have a lot of form data Here's 5 fields, maybe you even have more ... There are a few ways to address this --- #### Custom Hook ```jsx function useFriendForm() { const [firstName, setFirstName] = useState(''); // ... return { firstName, middleInitial, ... } } function FriendForm() { const form = useFriendForm(); // ... } ``` ??? - Extract state mgmt to a custom hook - Return whatever would be useful to original component - Original component now uses custom hook --- class: small, no-footer #### `useReducer` ```jsx const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error(); } } function FriendCounter({ initialState }) { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Count: {state.count}
dispatch({ type: 'increment' })}>+
dispatch({ type: 'decrement' })}>-
> ); } ``` ??? - NOT Redux - But a reducer is a concept used by redux - good when state is complex --- #### External Library ##### Formik ??? Or sometimes, using an external library might be an answer. The one we use for managing form data is called Formik. --- template: module-title layout: false # Side Effects ??? Side effect = interacting with anything outside of React & your React components. - Data fetching - Subscribing to a websocket - and manually changing the DOM --- layout: true template: module name: effects-section # Side Effects --- ## `useEffect` --- template: module-section layout: true name: use-effect-section # Side Effects ## `useEffect` --- ```jsx function Component(props) { useEffect( // arg 1: a function () => { * A; // what to do when effect fires return () => { * B; // what to do to clean up effect } }, // arg 2: an array * [ C ] // variables which should prompt effect to re-fire when changed ); return ... } ``` ??? 2 args, but 3 important things specified - nothing returned - A - B - C Examples: --- template: level-3 layout: true # Side Effects ## `useEffect` --- ### Loading Data ```jsx import callApi from './callApi'; function DetailItem(props) { const [item, setItem] = useState({}); useEffect(() => { async function load() { const item = await callApi(props.id); setItem(item); } load(); }, []); return ( ... ) } ``` ??? Loading data from an external source - callApi - an api client - useState - often, but not always associated with useEffect - async/await - useEffect can only return a function or nothing - so we can't mark the argument as async - first arg = what happens when the component mounts or the props change - no cleanup! - no props will cause it to re-fire - only fires once. --- ### Charting ```jsx function FriendsChart(props) { useEffect(() => { const graph = graphingLibrary.init(props.data); return () => { graph.destroy(); }; }, []); return ( ... ) } ``` ??? Integrating with a charting library - init based on props - store graph - return function - destroy graph - no props should cause re-fire --- ### WebSockets ```jsx function Chat(props) { useEffect(() => { socket.emit('join', { id: props.friendId }); return () => { socket.emit('leave', { id: props.friendId }); } }, [ props.friendId ]) return ( ... ) } ``` ??? Integrating with websockets - join a socket when effect fires - leave that socket to clean up the effect - re-run the effect when props.friendId changes --- template: exercise layout: false # Exercise 10 ## Loading Data ??? from an api & rendering components based on the results --- template: effects-section ## Suggestions --- template: level-2 layout: false # Side Effects ## Suggestions ### You Can Run Multiple Effects --- template: level-3 layout: false # Side Effects ## Suggestions ### Multiple Effects ```jsx function Component() { useEffect(() => { // Load Data }); useEffect(() => { // Charting }); useEffect(() => { // Websockets }); } ``` ??? If you have multiple things happening in an effect, break them up into separate calls No reason you can't do that Each one will be run. Advantage: easier to follow code --- template: module-title layout: false # Application State --- layout: true template: module name: app-state-section # Application State --- class: bg-contain background-image: url('images/drawings/state-tree-drilling.jpg') ??? app state is state that the entire app needs, or distant portions of it need. ... if we're elevating state, this means we have to pass props basically through the entire app this is called... --- ## Prop Drilling ??? all this prop drilling can feel like a burden, and noisy --- ## Context ??? and for app-level state, there's a fairly new api in react new in React 16.3 --- template: module-section class: bg-contain background-image: url('images/drawings/state-tree-ctx.jpg') # Application State ## Context ??? how context solves prop drilling - the top-most component will use the context as a "provider" - bottom components as "consumers" - anything under provider will have access to data from this context - w/o having to have props passed in - so props don't have to be drilled --- template: module-section layout: true # Application State ## Context --- ### createContext() ```javascript const UserContext = React.createContext(); ``` ??? the first thing you have to do is create a context this doesn't happen inside of a component it's something that executes alongside your components you get a provider & a consumer - like namespacing your context --- ### Provider ```jsx import UserContext from './user-context.js'; function UserProvider({ children }) { const user = useUser(); // however you get the logged in user return
{children}
; } ``` ??? - the provider will get wrapped around your component tree - value = the data you want to pass to consumers - user = however you got the user - maybe via useEffect,... --- ### Provider ```jsx import UserContext from "./user-context.js" function UserProvider({children}) { const user = ... // however you get the logged in user const handleUserChanged = ... // however you change the logged in user return (
{children}
); } ``` ??? value can be an object, if there are multiple things you want to pass down including **actions** that will change the value --- ### The Top Of Your Tree ```jsx import UserProvider from './user-provider.jsx'; function App() { return (
); } ``` ??? Then this wrapped provider gets imported into App & rendered at the top of the tree - mycomponenttree will be the children of UserProvider --- ### Consumer ```jsx import React, { useContext } from 'react'; function UserName() { const value = useContext(UserContext); return
{value.user.name}
; } ``` ??? and then all the places in the subtree that you need access to the state, you have consumers and they just want to know what the value of the context is using a hook named useContext --- ### Consumer ```jsx function CurrentUser() { const value = useContext(UserContext); return (
Current User: {value.userName}
Change User
); } ``` ??? for multiple things passed down via context... - note: not using fat-arrow for onClick because onUserChanged _is_ a function already --- template: exercise layout: false # Exercise 11 ## React Context ??? Poll: on your own? Or have me show you the code? --- template: app-state-section ## Deeper Learning --- template: module-section layout: true # Application State ## Deeper Learning --- ### Redux > Redux is a predictable state container for JavaScript apps. .footnote[ https://redux.js.org/ ] ??? one store to hold all the data and you connect your components to that state, so that when it changes, your component re-renders. --- ### Mobx > Simple, scalable state management .footnote[ https://mobx.js.org/ ] ??? reactive programming, observables updates get automatically applied --- template: app-state-section ## Suggestions --- template: module-section layout: true # Application State ## Suggestions --- ### Use The Right Tool ??? Component state: use useState Distant components: use context or Redux/mobx --- ### Read The Hooks Docs #### [reactjs.org/docs/hooks-intro.html](https://reactjs.org/docs/hooks-intro.html) ??? we've looked at only three hooks; docs have: - explanation of motivation - rules of use - a ton of other hooks - custom hooks --- ### `react-use` #### [streamich.github.io/react-use](http://streamich.github.io/react-use) ??? - a _ton_ of useful custom hooks --- template: module-title layout: false # Legacy Components ??? Prior to v16.8 --- layout: true template: module name: legacy-section # Legacy Components --- template: exercise layout: false # Exercise 12 ## Modern JavaScript: Class Syntax ??? Introduced recently Used by legacy react components --- ## React.Component ??? legacy components are classes that extend React.Component. --- template: module-section layout: false # Legacy Components ## React.Component ```javascript import React from 'react'; class FriendDetail extends React.Component { // ...Details about this component } ``` --- ## render() ??? The only requirement for a react **class** component is that it implements a render() function - comparable to the return value of a functional component --- template: module-section layout: false # Legacy Components ## render() ```jsx class FriendDetail extends React.Component { render() { return
...
; } } ``` ??? Note: class instance methods! --- ## Props ??? Props are accessed differently --- template: module-section layout: false # Legacy Components ## Props ```jsx class FriendDetail extends React.Component { render() { return (
{this.props.name}
); } } ``` ??? props are accessed on "this" - refers to the instance of the class that's being rendered --- template: exercise layout: false # Exercise 13 ## Converting Components ??? 10 minutes convert between a modern & legacy component --- template: exercise layout: false # Exercises 14 & 15 ## Legacy State Management & Side Effects ??? 10 minutes --- ## Suggestions --- template: module-section # Legacy Components ## Suggestions ### Don't Rewrite Everything --- template: module-title layout: false # Testing --- layout: true template: module name: testing-section # Testing --- ## Jest > Complete and ready to set-up JavaScript testing solution. Works out of the box for any React project. .footnote[ https://jestjs.io/ ] --- ## Jest ```javascript import aFunctionUnderTest from './a-function-under-test.js'; describe('A set of tests', () => { it('does a certain thing', () => { const result = aFunctionUnderTest(); expect(result).toEqual('a value'); }); }); ``` ??? describe it expect --- template: module-section # Testing ## Jest ### Matchers (Assertions) ```js expect(a).toEqual(b); expect(a).not.toEqual(b); expect(a).toBeGreaterThan(b); expect(a).toBeNull(); expect(a).toBeUndefined(); ``` ??? 35 available, some are valid only against certain types --- ## react-testing-library > Simple and complete React DOM testing utilities that encourage good testing practices. .footnote[ https://github.com/kentcdodds/react-testing-library/ ] ??? ... there are 3 things you're going to do in a test using react-testing-library: --- template: module-section layout: true name: react-testing-library # Testing ## react-testing-library --- class: no-footer ### 1. Render Components ```jsx *import { render } from 'react-testing-library'; import FriendDetail from './FriendDetail'; describe('FriendDetail', () => { it('renders something', () => { const friend = { ... }; * const context = render(
* ); // ... }); }); ``` ??? you're going to render your component --- ### 2. Find Elements ??? find elements that were rendered ... and find them the way a user would - -- ```jsx const context = render(
); * const loadingText = context.queryByText('Loading...'); ``` -- ```jsx const context = render(
); * const friendImage = context.queryByAlt('Mr. Cat The Mystery Cat'); ``` -- ```jsx const context = render(
); * const loadingText = context.queryByTestId('friend-container'); ``` ??? you might make assertions against what was rendered & found - like ex 1 exists - there's 2 of ex 2 - ex 3 doesn't exist --- template: exercise layout: false # Exercise 16 ## Testing Component Render --- ### 3. Fire Events ```jsx *import { render, fireEvent } from 'react-testing-library'; describe('...', () => { it('...', () => { const context = render(
); const button = context.queryByText('Details >'); * fireEvent.click(button); }); }); ``` ??? To test interactions of components, you'll fire DOM events against the elements, using fireEvent. --- template: exercise layout: false # Exercise 17 ## Testing Component Interactions --- template: testing-section ## Deeper Learning --- template: module-section # Testing ## Deeper Learning ### Enzyme #### http://airbnb.io/enzyme/ ??? enzyme does a LOT of stuff; react-testing-library tries to keep the possibilities to things that users care about --- template: module-section # Testing ## Deeper Learning ### Jest-DOM #### https://github.com/gnapse/jest-dom ??? for more matchers that let you identify classes, attributes, things on DOM elements --- template: testing-section ## Suggestions --- template: module-section layout: true # Testing ## Suggestions --- ### Async Helpers ```jsx it('shows details after clicking button', async () => { const context = render(
); const button = context.getByText('Details'); fireEvent.click(button); * const details = await waitForElement(() => * context.getByText('snuggles like a champion')); // ... }); ``` ??? specific to react-testing-library async events are usually hard to test but not with rtl - A: render - B: click a button - C: wait for an element to appear - D: make some assertion, ... --- ### Async Helpers ```jsx async wait async waitForElement async waitForDomChange ``` ??? Async helpers available - all wait 4500 ms by default --- ### Extract Complexity & Logic ??? more general suggestions: testing logic outside of components is easier than testing logic inside of components --- ### Test What The User Experiences #### Not Implementation ??? Avoid testing for presence of css classes, unless it's the only way to prove something is working Prefer testing presence of text elements react-testing-library forces you to do this --- class: bg-contain background-image: url('images/drawings/testing-pyramid.jpg') ### Write "Unigration" Tests ??? unit tests are small & people can be overly dogmatic about what defines a "unit" integration tests are too slow & we can tell a lot from our app without pulling in db/api's --- class: bg-contain background-image: url('images/drawings/testing-pyramid-unigration.jpg') ### Write "Unigration" Tests ??? somewhere in the middle of those is the "unigration" zone --- template: level-3 layout: false class: bg-contain, no-footer background-image: url('images/drawings/unigration-tree-1.jpg') # Testing ## Suggestions ### Write "Unigration" Tests ??? if you're trying to test that component at the top of this subtree, --- template: level-3 layout: false class: bg-contain, no-footer background-image: url('images/drawings/unigration-tree-2.jpg') # Testing ## Suggestions ### Write "Unigration" Tests ??? test component tree with all helper functions included mock things that are slow/we don't own (api's) --- ### Write Tests For Future You ??? You have all the context right now. You three months from now does not. Consider what they'll go through when they find a failing test! Make it easier for them to figure out. --- template: module-title layout: false # Good Practices --- layout: true template: module name: good-practices-section # Good Practices --- ## create-react-app ### [bit.ly/create-react-app](https://bit.ly/create-react-app) ??? problem solved: setting up webpack & react & other dependencies is difficult --- layout: false template: module-section class: bg-contain, no-footer background-image: url('images/drawings/create-react-app.jpg') # Good Practices ## create-react-app ??? spins up an app for us sensible defaults hides complexity of webpack, etc from us if I were starting an app, I would use create-react-app. --- ## Thinking In React ### [reactjs.org/docs/thinking-in-react.html](https://reactjs.org/docs/thinking-in-react.html) ??? --- template: module-section layout: true # Good Practices ## Thinking In React --- #### **Step 1:** Break The UI Into A Component Hierarchy -- #### **Step 2:** Build A Static Version in React -- #### **Step 3:** Identify The Minimal (but complete) Representation Of UI State -- #### **Step 4:** Identify Where Your State Should Live -- #### **Step 5:** Add Inverse Data Flow --- template: good-practices-section layout: true --- ## Isolate Complexity ??? Try to make as many simple, dumb, functional components as possible Push the complicated things & stateful things to the edges This makes it easier to understand most of your app --- ## Break Into Pieces ??? In general, this is a good strategy for problem-solving It also is in regards to React But it is ALSO a good strategy to make sure your components are small & easy to maintain. --- ## Code That Changes Together Should Live Together ??? I mean this in a couple ways: 1. our new way of looking at separation of concerns markup + js + css but also, 2. when organizing code in your app When grouped by file type, you have to bounce around to work on a feature When grouped by feature, all you need is in one folder --- template: module-title # Feedback ## Green = Good; Yellow = Okay; Pink = Bad --- layout: false template: cover-art class: thank-you # Thank You! .about[ ## Steven Hicks ### [@pepopowitz](https://twitter.com/pepopowitz)
### steven.j.hicks@gmail.com
### [stevenhicks.me/your-first-react-app](https://stevenhicks.me/your-first-react-app)
] ??? I want to thank you for your time I really appreciate it. Survey Questions after Thank you! --- template: level-1 class: double-wide, resources # Resources - [Workshop materials](https://stevenhicks.me/your-first-react-app) --- template: level-1 class: double-wide, resources # Images - [Frank McKenna](https://unsplash.com/photos/tjX_sniNzgQ) - Title