icon cloudapp
icon email
5 Things You'll Love About React
Steven Hicks
@pepopowitz
steven.j.hicks@gmail.com
stevenhicks.me/5-things-about-react
My kids when they were in kindergarten got to make a huge poster when they were the "star student"
Where they put everything you need to know about them
So I did the same
Milwaukee
JS
Super cool letter S
Family
Outdoors/trail running
Engineer at Artsy
NYC, MKE
our mission is to expand the art market,
and we're doing that with a platform for collecting and discovering art.
20+ years experience as a JS developer
Many ways I've built JS apps
My user journey
plain js
hard to write code
hard to write an app
jquery
amazing
easy to write code
hard to write an app
mv*
angular, backbone, knockout
easy to write code, hard to write an app (ko)
easy to write an app, hard to write code (angular)
And now I'm building apps with React, and have been for the last few years, and I'm really happy.
easy to write code
easy to write app
...
Because I have 5 things to present, I need a clever way to present a list
Your browser does not support the audio element.
Your browser does not support the audio element.
1. Components
Build encapsulated components that manage their own state, then compose them to make complex UIs.
reactjs.org
straight from docs
This is different from when we were doing MVC/MVVM
And the other major players right now are doing the same thing
1. Components
And those components are composed of other components
...
This is actually an activity I do when I'm developing a new feature:
Draw out the component boundaries before I start coding it.
...
But if we do a good job of identifying our component boundaries,
1. Components
And we can build bigger blocks with those legos,
1. Components
https://your-first-react-app.stevenhicks.me/#p82
In order to do this well, we really need to focus on isolation of our components.
(left image: not properly isolated, one component that does several things)
(right image: properly isolated; components are building blocks.)
1. Components
Isolation of components leads to reusability
1. Components
The most important contribution from React is thinking in terms of components
Components aren't unique to react,
but React popularized this approach
and it is IMO the single biggest contribution from React.
1. Components
Conceptually, components are like JavaScript functions . They accept arbitrary inputs ... and return React elements describing what should appear on the screen .
reactjs.org
1. Components
Are Functions
1. Components
Are 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.
reactjs.org
they should be pure
what's a pure function?
1. Components
Are Functions
And Are Pure
A pure function:
is deterministic
does not have side-effects
1. Components
Are Functions
And Are Pure
Pure ππ½
function add (a, b) {
return a + b;
}
1. Components
Are Functions
And Are Pure
Impure π
function now ( ) {
return new Date ();
}
1. Components
Are Functions
And Are Pure
Impure ππ½
function decrement ( ) {
this .x = this .x - 1 ;
}
1. Components
Are Functions
import React from 'react' ;
function Artist (props ) {
console .log(props.name, props.url);
}
Here's what a function component looks like.
This is a component that isn't actually rendering , it's just logging
But you can see it's got two inputs being passed in via props - a name and a url.
...
if this is what inputs look like; how does it render to the browser?
1. Components
Are Functions
createElement
function Artist (props) {
return React.createElement('div') ;
}
<div />
using a helper from React named createElement
Give it the element type
...
rendered to browser as a div
1. Components
Are Functions
createElement
function Artist (props) {
return React.createElement(
'div ',
{ id: 'artist -wrapper' },
'Hi !'
);
}
<div id ="artist-wrapper" >Hi!</div >
2nd arg - attributes to apply to element
3rd arg - child elements!
1. Components
Are Functions
createElement
function Artist (props) {
return React.createElement(
'div ',
{ id: 'artist -wrapper' },
props.name
);
}
<div id ="artist-wrapper" >Andy Warhol</div >
We can use a prop as a child text element!
When the prop changes, React will re-render
1. Components
Are Functions
createElement
function Artist (props ) {
return React.createElement(
'div' ,
null ,
React.createElement('h1' , null , 'Artworks by ' + props.name)
);
}
<div >
<h1 > Artworks by Andy Warhol</h1 >
</div >
We've looked at some simple examples, but usually our components are more complex
We might want to render markup like this:
1. Components
Are Functions
createElement
<div id ="artist" >
<div id ="bio" >
<h1 > Andy Warhol</h1 >
<h2 > American, 1928 - 1987</h2 >
</div >
<div id ="photo" >
<a href ="/artists/andy-warhol" >
<img src ="/artists/andy-warhol/image" alt ="Andy Warhol" />
</a >
</div >
</div >
And in that case, the createElement statements would look like this:
1. Components
Are Functions
createElement
function Artist (props) {
return React .createElement (
'div' ,
{ id : 'artist' },
React .createElement (
'div' ,
{ id : 'bio' },
React .createElement ('h1' , null, props.name),
React .createElement ('h2' , null, props.origin + ', ' + props.lifespan)
),
React .createElement (
'div' ,
{ id : 'photo' },
React .createElement (
'a' ,
{
href : '/artists/' + props.id,
},
React .createElement ('img' , {
src : props.profileImageUrl,
alt : props.name,
})
)
)
)
}
As you can see, that's just not sustainable.
So while you'll build your UI with a series of React.createElement calls,
there's another abstraction you'll want to use that will make your life easier.
And that brings us to....
Your browser does not support the audio element.
2. JSX
function Artist () {
return React.createElement('div') ;
}
function Artist () {
return <div />;
}
Here's our first example from before - React.createElement to render a div.
...
Here's what it looks like as JSX
(PAUSE)
note - no quotes around angle brackets
2. JSX
function Artist (props) {
return React.createElement(
'div ',
{ id: 'artist -wrapper' },
props.name
);
}
function Artist (props ) {
return (
<div id ="artist-wrapper" >
{props.name}
</div >
)
}
example that renders a name
(PAUSE)
you might think you'll hate it
combo of xml & javascript, yikes!
but react.createElement is verbose & gross
2. JSX
function Artist (props) {
return React .createElement (
'div' ,
{ id : 'artist' },
React .createElement (
'div' ,
{ id : 'bio' },
React .createElement ('h1' , null, props.name),
React .createElement ('h2' , null, props.origin + ', ' + props.lifespan)
),
React .createElement (
'div' ,
{ id : 'photo' },
React .createElement (
'a' ,
{
href : '/artists/' + props.id,
},
React .createElement ('img' , {
src : props.profileImageUrl,
alt : props.name,
})
)
)
)
}
remember this more complicated component?
With JSX, it looks like this:
2. JSX
function Artist (props ) {
return (
<div id ="artist" >
<div id ="bio" >
<h1 > {props.name}</h1 >
<h2 > {props.origin}, {props.lifespan}</h2 >
</div >
<div id ="photo" >
<a href ={ '/artists /' + props.id }>
<img src ={props.profileImageUrl} alt ={props.name} />
</a >
</div >
</div >
)
}
2. JSX
Separation Of Concerns
Often when people see JSX, they start talking about "separation of concerns"
2. JSX
Separation Of Concerns
And our instinct as engineers, historically, is to separate our code into layers
keep your HTML with your HTML, JS with JS, ...
2. JSX
Separation Of Concerns
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.
reactjs.org
React addresses this claim head-on
Stating that this traditional separation is a separation of technologies , not concerns
(read it)
2. JSX
Separation Of Concerns
When you're thinking in components, you can scrap the technological layers
The concern is each individual component
(PAUSE)
2. JSX
function Artist (props ) {
if (props.name === 'Andy Warhol' ) {
return <div > I like your soup cans!</div > ;
}
return <div > You make nice art.</div > ;
}
Because JSX is a superset of JavaScript,
we can write our components entirely in JS
No templating languages necessary.
Here's a component that's using an if to decide which div to render.
We get to use latest ES features anywhere in our code.
2. JSX
Components in JSX lead to declarative code
Let's talk a bit about why that matters,
and we'll start with what it means for code to be declarative.
2. JSX
Declarative
Q: How do you get to my house?
if you ask me how to get to my house,
I can answer two ways
2. JSX
Declarative
Q: How do you get to my house?
2. JSX
Declarative
Q: How do you get to my house?
Or I can tell you my address
And I can leave it up to you to figure out the "how"
this is declarative
it tells you WHAT my address is, and leaves the HOW to you.
2. JSX
Declarative
var artistsComingToMyParty = [];
for (var i = 0 ; i < artists.length ; i++) {
var artist = artists[i];
if (artist.rsvp === true ) {
artistsComingToMyParty.push (artist);
}
}
var artistsComingToMyParty = artists.filter(
artist => artist.rsvp === true );
or in code, the difference is illustrated here
top: Imperative
bottom: declarative
2. JSX
Declarative
Imperative code is abstracted so that we can call it declaratively
It's important to note, the imperative code doesn't just evaporate
Often we have to abstract it before other code can call it declaratively
2. JSX
Declarative
Declarative views make your code more predictable and easier to debug .
reactjs.org
Your browser does not support the audio element.
3. New Features
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
3. New Features
Hooks
useState
3. New Features
Hooks
State Management
remember the drawing of a component as f(props)?
it was a lie!
3. New Features
Hooks
State Management
Components are actually functions of both their props and their state
...
props are passed into a component
state is contained within a component
and the component manages it.
Examples:
the checked state of a checkbox.
the current value of a counter
...
when you update props OR state of a component, React re-renders it
3. New Features
Hooks
State Management
Once you have a component managing its state,
it can pass it down to its children as props
This is a really common thing to do in React-
elevate the state to the highest level that any other component would need it, and manage it there.
...
When it comes to ways to manage state, you've got options!
3. New Features
Hooks
useState
function Counter ( ) {
const [count, setCount] = useState(0 );
return (
<div >
Count: {count}
<button onClick ={() => setCount(count + 1)}>Increment</button >
<button onClick ={() => setCount(count - 1)}>Decrement</button >
</div >
);
}
3. New Features
Hooks
useState
useReducer
useContext
Other means of managing state:
useState: For managing component state
useReducer: For managing more complicated state
useContext: For managing state across large subtrees
...
You might notice a pattern - all start with "use"
3. New Features
Hooks
useEffect
function ArtistDetails (props ) {
const [artist, setArtist] = useState(null )
useEffect(() => {
const apiArtist = loadArtistFromApi(props.artistId)
setArtist(apiArtist)
}, [])
return ( ... )
}
3. New Features
Hooks
useEffect
function Chat (props ) {
useEffect(() => {
socket.emit('join' , { id : props.friendId });
return () => {
socket.emit('leave' , { id : props.friendId });
}
}, [ props.friendId ])
return ( ... )
}
For performing side-effects from a component
What to do to fire the effect
what to do to clean up the effect
when the effect should re-run
...
Notice: the "leaving" of a socket is going to happen in the future sometime
but we're still able to reference the friendId prop from when it rendered
3. New Features
Hooks
Closures
A closure is the combination of a function and the lexical environment within which that function was declared.
developer.mozilla.org
That's because JavaScript forms closures over variables when you declare a function
This is really helpful for the useEffect
hook especially, and its multiple callback functions:
3. New Features
Hooks
useEffect
function Chat (props ) {
useEffect(() => {
socket.emit('join' , { id : props.friendId });
return () => {
socket.emit('leave' , { id : props.friendId });
}
}, [ props.friendId ])
return ( ... )
}
you know when your cleanup function executes, it's going to disconnect from the right friend's socket
...
But that's the happy path to closures in JavaScript.
They can be really difficult to understand and manage, even in React hooks,
Your browser does not support the audio element.
3. New Features
Suspense
Suspense lets components βwaitβ for something before rendering.
reactjs.org
This is a really neat way to solve the problem that it takes time for browsers to load things.
Until Suspense, we've had to manage "isLoading" flags all over our app
3. New Features
Suspense
const ArtistGraphs = React.lazy(() => import ('./ArtistGraphs' ));
function Artist ( ) {
return (
<React.Suspense fallback ={ <Loading /> }>
<ArtistGraphs />
</React.Suspense >
);
}
now, we can use React Suspense to emit fallback content,
like a loading indicator,
until something finishes loading.
...
That currently includes the ability to load the code for a component separate from the main application, lazily, when the user actually needs it,
Soon, it will include the ability to emit fallback content
until data fetching is complete for a component
3. New Features
Backwards compatible
released as "Minor" version
Backwards compatible - you can do things the old way, too
This shows the care & consideration the React team takes to let you build your app the way YOU want to
Your browser does not support the audio element.
#3 on the board
The developer experience in React is top-notch
starting with some non-react specifics, that you'd want in any framework
4. Developer Experience
Hot-reloading
When you're dev'ing locally, you make changes and see changes instantly in your browser
4. Developer Experience
webpack
integrates really easily with webpack
reduces size of JavaScript bundle via tree-shaking, which removes unused code
if you don't have to worry about configuring it. That can be confusing.
4. Developer Experience
babel
function Artists ({ artists } ) {
return artists.map(artist => <ArtistDetail {...artist} />);
}
4. Developer Experience
TypeScript
4. Developer Experience
TypeScript
interface ArtistProps {
name : string,
origin : string,
url : string
}
function Artist (props: ArtistProps ) {
return (
<div id ="artist" >
<h1 >
<a href ={props.url} > {props.name}</a >
</h1 >
<h2 > {props.origin}</h2 >
</div >
)
}
Describe types
interface
strings
props: ArtistProps
4. Developer Experience
TypeScript
when you use TS, you get compile-time errors about missing props
Your browser does not support the audio element.
You might be catching on that there are a lot of decisions to be made
Something like Angular or Ember is going to tell you how to do things, and not leave you a lot of freedom
React will leave you a lot of freedom in your implementation
But that can be a thing that is really overwhelming.
4. Developer Experience
Prettier
one tool that can help you eliminate some decisions is called Prettier
prettier is an opinionated code-formatter
...
so you can write your code however you want
and prettier will autoformat for you, and everyone on your team
so you never have to worry about arguing over style
4. Developer Experience
React Dev Tools
It makes it really easy to see if your component is getting the props you're expecting
which is really useful for debugging
4. Developer Experience
Performance baked into react
you're guided to the pit of success
Some neat techniques to make sure your app renders quickly...
4. Developer Experience
Performance
Reconciliation
including the most well-known, Reconciliation
aka virtual-dom diffing
renders component to a "virtual" dom
compares that virtual dom to actual dom
only updates that which has changed
perf because slowest part of any UI is the actual commits to the DOM.
...
One more piece of the developer experience is so great that it warrants its own place on our list -
...
Your browser does not support the audio element.
#5 on the board
I am a huge fan of writing automated tests in general
and the tooling for writing tests in React is the best I've experienced.
5. Testing
Jest
Jest is a delightful JavaScript Testing Framework with a focus on simplicity .
jestjs.io
jest is not required to test React,
and React isn't required to use Jest
but Jest was born out of the React community
5. Testing
Jest
Easy setup
5. Testing
Jest
Interactive watch mode
5. Testing
Jest
Great error messages
helps you quickly identify what's wrong with your test
5. Testing
Jest
describe('findSimilarArtists' , () => {
it('finds similar artists for Andy Warhol' , () => {
const result = findSimilarArtists('Andy Warhol' );
expect(result[0 ]).toEqual('Robert Indiana' );
});
});
syntax
describe
it
act
assert
assertions are called "matchers"
5. Testing
Jest
expect(a).toEqual(b);
expect(a).not.toEqual(b);
expect(a).toBeGreaterThan(b);
expect(a).toBeNull();
expect(a).toBeUndefined();
Over 30 different matchers out of the box
You can write custom ones
5. Testing
react-testing-library
And then for specifically testing React,
there's a great library called r-t-l
You can use it with Jest
5. Testing
react-testing-library
describe('ArtistDetail' , () => {
it('renders something' , () => {
const context = render(
<ArtistDetail artist ={...} />
);
β
β
β
β
β
β
β
});
});
5. Testing
react-testing-library
describe('ArtistDetail' , () => {
it('renders something' , () => {
const context = render(
<ArtistDetail artist ={...} />
);
const button = context.queryByText('Details');
fireEvent.click(button);
β
β
β
β
});
});
...interacting with elements...
5. Testing
react-testing-library
describe('ArtistDetail' , () => {
it('renders something' , () => {
const context = render(
<ArtistDetail artist ={...} />
);
const button = context.queryByText('Details');
fireEvent.click(button);
expect(context.getByTestId('artist-details'))
.toHaveTextContent('Andy Warhol')
});
});
asserting presence of elements
...
There are other libraries for testing React, too - Enzyme is a popular one
But this is the boss hog of testing in react.
Getting started
create-react-app
Getting started
create-react-app
> create-react-app my-app
Before I close, I want to give a thank you
to the creators of the lego artsy site you saw earlier
My daughters Lila and Olivia
Who think they are going to be famous because they're in this talk and I don't have the heart to tell them otherwise.
Your browser does not support the audio element.
Thank you!
Steven Hicks
@pepopowitz
steven.j.hicks@gmail.com
stevenhicks.me/5-things-about-react
Thank you for your time!
Questions afterward
Enjoy the rest of ___
icon cloudapp
icon email
icon twitter
5 Things You'll Love About React
Steven Hicks
@pepopowitz
steven.j.hicks@gmail.com
stevenhicks.me/5-things-about-react