relay: seamless syncing for react (vanjs)
TRANSCRIPT
RELAYBROOKLYN ZELENKA
SEAMLESS SYNCING FOR REACT
A LITTLE ABOUT BROOKESHAMELESS SELF PROMOTION
• Full stack developer at MetaLab and Robot Overlord
• Come see me for stickers and buttons after the talk 😉
• Organizes a few meetups
• Leaving the country in February, so giving a few talks before then
• Have been using Relay “professionally” since October 2015
• ~6 weeks after the initial technical preview was open-sourced
• Maintain awesome-relay, but honestly there’s not a ton written about Relay yet (repo will grow when there is more)
ONCE UPON A TIME…VALUE PROPOSITION
• GraphQL + Relay version• Took roughly a day• Built a GraphQL type and tested it
• “Can we have a RESTful version for the old API?”• Marty + REST version
• Took the most of the remainder of the week• Had to build a custom route, controller, presenter, and serializer…• …and then write tests for everything above
REACT + GRAPHQL + HELPERS = RELAYWHAT WE’RE GOING TO COVER
• Why another front-end framework?
• A brief React refresher
• GraphQL
• Relay
• Closing thoughts
• Q&A
ANOTHER FRAMEWORK?
THINGS WORK, SO WHY BOTHER LEARNING ANOTHER FRAMEWORK?
ANOTHER FRAMEWORK?
DEVELOPER HAPPINESS IS IMPORTANTBECAUSE FUN!
• It can’t be overstated as an important factor in long-term project success
• It’s fun to learn new things, be on the leading edge, &c
• It’s fun to contribute back to young project, or even open an Issue on the repo
• Removing boilerplate helps us get more done faster, which makes us feel good!
INDIVIDUAL AND INDUSTRY PROGRESS ARE IMPORTANTBECAUSE PROGRESS!
• Otherwise our jobs would still involve writing FORTRAN on punch cards
• Open progress as a collective profession gets more eyes than internal solutions
EXPERIMENTING WITH NEW WAYS OF DOING THINGS IS IMPORTANTBECAUSE NEW IDEAS!
• It might not end up being The One True Way, but it still a progression towards The Next Big Thing
DIFFERENT FRAMEWORKS HAVE DIFFERENT STRENGTHS & GOALSBECAUSE DIFFERENT USE CASES!
RELAY ISN’T GOING TO DISAPPEARBECAUSE FACEBOOK!
• Relay is Facebook backed
• Not disappearing any time soon
• Tied to the future of other tech, like React Native
THE PROBLEM
EFFICIENTLY SYNCING DATA IS HARDTHE PROBLEM
• Generally, we need a way to read from and write to a server
• Projects start simple: a single RESTful endpoint can describe what’s on the page
• But eventually…
• Pages start to require data from multiple resources
• Different pages need different attributes from the same resource
EXISTING SOLUTIONS
WRITE A CUSTOM ENDPOINT FOR EACH USE CASEEXISTING SOLUTIONS
• Write a custom API endpoint for each use case
• No over- or under-fetching (if you’re willing to put in the time)
• Doesn’t scale: time consuming; brittle; confusing
THE CANONICALLY RESTFUL WAYEXISTING SOLUTIONS
• Write general RESTful endpoints for each resource
• Can use multiple queries to load data for several resources
• Often get less data than you need (under-fetching)
• Therefore can need multiple requests
• Often get more data than you need (over-fetching)
• Requests are larger than they need to be (inefficient)
PRE-FETCH EVERYTHING THAT THE USER MIGHT WANT`
• Prefetch all of the data that the user might want on initial page load
• Inefficient (serious over-fetching) & poor performance
EXISTING SOLUTIONS
WHAT IF THE CLIENT CONTROLLED THE RESPONSE SHAPE?THERE MUST BE A BETTER WAY
• Wouldn’t it be nice if we could…• ask the server for specific information, ad hoc• compose queries• nest queries to mirror the UI’s nesting
• Facebook has a pretty popular website, and make frequent changes• Updating a RESTful API would not keep up• Explored a few solutions; settled on their GraphQL
• Netflix and Cognitect have come up with similar solutions• Falcor• The Om Next data resolver + Datomic
REACTA QUICK REFRESHERBEFORE WE GO ON
REACTPHILOSOPHYVIRTUAL DOMJSXCOMPONENTS
I’M GOING TO MOVE SOMEWHAT QUICKLY, OTHERWISESTOP ME IF SOMETHING IS UNCLEAR
MORE THAN “THE V IN MVC”PHILOSOPHY
• A functional approach• Limit & control state
• Prefer keeping your data unchanged (immutable)• Isolate any changing (mutable) data
• Components are functions that take props and return a chunk of Virtual DOM• Declarative (“what”) > imperative (“how”)• Data flow• Of course, DRY
JS OBJECT UPDATES ARE MUCH FASTER THAN A BROWSER’S RENDERERVIRTUAL DOM
• Instead of manipulating the DOM directly, we update a JSON representation it• Can then diff the DOM, and make focused changes• This makes re-rendering extremely fast
• We only get real DOM changeswhen we need then
• Get multiple changes at once (no flickering in and out)
• HTML & JSX are trees, so parents “own” their children
WHO PUT HTML IN MY JS?JSX
• Handy HTML-like syntax that compiles down to pure JS
• Can mix and match with HTML elements (more or less)
• Pass arguments as “props”
• Nested elements are “props.children”
WHO PUT HTML IN MY JS?JSX
ROLL YOUR OWN HTML TAGS
• Can write custom components for your display logic
• Just assign a name to the JSX (or plain JS) from previous slide
• Take props, and render plain HTML
COMPONENTS
ROLL YOUR OWN HTML TAGS COMPONENTS
GRAPHQLIDEOLOGYDECLARATIVE SYNTAXTYPESQUERIESMUTATIONSINTROSPECTION
SINCE ALL SCHEMAS ARE TECHNICALLY GRAPHS…IDEOLOGY
• “REST gives you data per resource, so let’s try something else”• Being RESTless(?) is developer heresy• One endpoint to rule them all; usually /grahql
• Request only what you need• Let the server figure out how
• Want JSON to express relationships between objects, but get duplication• So, dedup nodes that have multiple connections
• Graphs are strictly more expressive than relational schemas• Can rewrite any relational structure as a graph
“I WANT SOME DATA THAT LOOKS LIKE THIS“DECLARATIVE SYNTAX
GETTING CONTRACTS INTO YOUR APPLICATIONTYPES
• User definable “shapes” or “structs”
• Fields be required or optional
• Enforce data consistency
• Catch bugs early
• Keep the database clean
• Doubles as documentation
THE “GET REQUEST” OF GRAPHQLQUERIES
PASSING ARGUMENTSQUERIES
Set up like a function(arguments -> graph fragment)
THE “PUT/POST/DELETE/SIDE-EFFECT” OF GRAPHQLMUTATIONS
• “Mutations” are how you change (“mutate”) the world outside of the FE app
• Update a field in the database
• Send an email
• Fire the missiles
• Set up like a function (arguments -> graph fragment)
THE “PUT/POST/DELETE/SIDE-EFFECT” OF GRAPHQLMUTATIONS
ORDER A SIDE OF DOCS WITH YOUR APIINTROSPECTION
• Can construct a regular query to get metadata• First-class!• The schema itself
• the whole thing, or just a portion• Descriptions of fields• Descriptions and fields on types• Descriptions and fields on mutations
• Which fields are required• What the fragments it can return are• &c.
GRAPHQL LIVE DEMO
RELAYARCHITECTURECONTAINERSLOCAL VS REMOTE DATAPROS & CONSTOOLS
IT’S PRETTY NEW™RELAY
• React was publicly released at the end of May, 2013
• Relay’s technical preview made available in mid-August, 2015
• Facebook has been using parts of it internally for a while (~2 years?)
• They have also been using GraphQL with iOS applications for a while, too
FLUX-ISHARCHITECTURE
MAGICAL BOXES TO HANDLE YOUR COMPONENT’S DATA NEEDSCONTAINERS
• Wraps a “plain” component (HOC)
• Fetches data from the server
• Translates GraphQL to JSON
• Composable (KILLER FEATURE)
OSTENTATION FTW!CONTAINERS
TALKING TO THE OUTSIDE WORLDMUTATIONS
SEPARATION OF REMOTE AND LOCAL DATATRULY LOCAL DATA
• Relay really wants its client and server stores to be consistent
• If some data is not going to be synced to the server, it doesn’t belonging the graph
• Store such data in the React component state
• ex. partially filled form fields, locked buttons, which tab is visible, &c
• One store for Relay’s synced (“remote”) data, and several for purely local data
IT’S LIKE THEY WERE NEVER HEREEPHEMERAL DATA
• Relay doesn’t really directly handle temporary data
• For example, let’s say the we want a temporary token that will not be persisted
• We have three options:
• Plain REST
• Plain GraphQL
• Fake it with a null node
FAKE IT ‘TILL THEY MAKE ITTHE NULL NODE KLUDGE
• Create an attribute on the User type node that returns null by default (initial query)
• Mutation to create the token
• Input: {userID: “PF8bxC7R51”}
• Output: {user { id: “PF8bxC7R51”, token: “i3g7BrhwHb” }}
• ie: works as normal
• This data probably doesn’t “belong” on the user, but it’s a convenient location
• If you refresh the page, you’ll need to go through the mutation again
PRETTY GREAT, BUT IT’S NOT ALL KITTENS AND RAINBOWSPROS AND CONS
👍 Speeds up development
👍 Keeps things flexible
👍 Fun to use
👍 Very active repo
👍 Smart people working on it
👍 Feels like the future
👍 It’s (very) early days
👍 Documentation “could be better”
👍 Some unintuitive naming
👍 Few complete examples
👍 Bugs are sometimes the framework
👍 Doesn't handle local data
Q&A