Share
Embed
Functioning in React: A Deep-Dive into useState
The State Hook is now a core part of React. But what does it mean for a function to have state? This talk explores this question, touching on the history of state, the source code behind the hook, and the impact stateful functions have on the code we write.
Jake Worth
October 03, 2019
Transcript
66 slides
-
"[I]f he doesn't understand something, he just asks you. He
doesn't care if he sounds foolish... he will ask the most obvious question without any sort of concern about it... so he asks lots and lots of 'dumb,' in the best sense of that word, questions. He'll say to someone, 'I don't understand. Explain that to me.' He'll just keep asking questions until he gets it right." — Malcolm Gladwell1 1 Ferriss 2016, 573. @jwworth 3 -
» ! Jake Worth / @jwworth » " Hashrocket »
# Today I Learned » $ https://www.jakeworth.com/ @jwworth 6 -
Agenda 1. History of State 2. State Hooks Deep-Dive 3.
Hooks In My Code? @jwworth 13 -
History of State: CS "Stateful means the computer or program
keeps track of the state of interaction, usually by setting values in a storage field designated for that purpose. Stateless means there is no record of previous interactions and each interaction request has to be handled based entirely on information that comes with it."2 2 Whatis.com 2019. @jwworth 15 -
History of State: CS "Stateful means the computer or program
keeps track of the state of interaction, usually by setting values in a storage field designated for that purpose. Stateless means there is no record of previous interactions and each interaction request has to be handled based entirely on information that comes with it."2 2 Whatis.com 2019. @jwworth 16 -
History of State: CS » Stateless interaction: HTTP » Stateful
interaction: Browser & localStorage » Imperative programming languages: JavaScript @jwworth 17 -
History of State: CS "In computer science, imperative programming is
a programming paradigm that uses statements that change a program's state."3 3 Wikipedia 2019. @jwworth 18 -
History of State: React » ES3 module pattern » ES6
component classes » Stateless functional components » Class-fields syntax » Stateful functional components (Hooks) @jwworth 19 -
History of State: React 0.13 // ES3 module pattern function
PirateShip(initialProps) { return { state: { cannonsCount: 0 }, render: function() { return <div>{this.state.cannonsCount} cannons</div>; }, }; } @jwworth 21 -
History of State: React 0.13 // ES6 component classes class
PirateShip extends React.Component { constructor(props) { super(props); this.state = { cannonsCount: 0 }; } render() { return <div>{this.state.cannonsCount} cannons</div>; } } @jwworth 22 -
History of State: React 0.13 // Updater function this.setstate((state, props)
=> { return { cannonsCount: state.cannonsCount + 1 }; }); // First-argument object this.setstate({ cannonsCount: 100 }); @jwworth 23 -
History of State: React 0.14 "In idiomatic react code, most
of the components you write will be stateless."4 4 Alpert "React v0.14" 2015. @jwworth 24 -
History of State: React 0.14 // ES6 arrow function var
PirateShip = props => { var cannonsCount = props.cannonsCount; return <div>{cannonsCount} cannons</div>; }; @jwworth 25 -
History of State: React 0.14 & ES6 // Class-fields syntax
class PirateShip extends React.Component { state = { cannonsCount: 0 }; render() { return <div>{this.state.cannonsCount} cannons</div>; } } @jwworth 26 -
History of State: React 16.8 // useState function PirateShip() {
const [cannonsCount, setCannonsCount] = useState(0); return <div>{cannonsCount} cannons</div> } @jwworth 27 -
History of State: React 16.8 // useState w/ multiple slices
function PirateShip() { const [cannonsCount, setCannonsCount] = useState(0); const [anchored, setAnchored] = useState(false); // return JSX } @jwworth 28 -
History of State: React 16.8 // useState function PirateShip() {
const [cannonsCount, setCannonsCount] = useState(0); // return JSX } @jwworth 29 -
State Hooks Deep-Dive: Below » ! Multiple packages » "
Type-safety » # Dependency injection » $ Interesting comments » % Leaps of faith @jwworth 31 -
// Our code function PirateShip() { const [cannonscount, setCannonsCount] =
useState(0); // return JSX } @jwworth 33 -
// Our code import React, { useState } from 'react';
// function PirateShip() { const [cannonscount, setCannonsCount] = useState(0); // return JSX } @jwworth 34 -
State Hooks Deep-Dive: Split » React 0.14 Package split: react
& react-dom » Renderers: react-dom, react-dom/server, react-native, react- test-renderer, react-art @jwworth 35 -
// packages/react/index.js const React = require('./src/React'); // TODO: decide on
the top-level export form. // This is hacky but makes it work with both // Rollup and Jest. ! module.exports = React.default || React; @jwworth 36 -
// packages/react/src/React.js import { useState } from './ReactHooks'; const React
= { useState, }; export default React; @jwworth 37 -
// packages/react/src/React.js import { useState } from './ReactHooks'; const React
= { useState, __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: ReactSharedInternals, // }; export default React; @jwworth 38 -
// packages/react/src/React.js import { useState } from './ReactHooks'; const React
= { useState, }; export default React; @jwworth 39 -
// packages/react/src/ReactHooks.js export function useState<S>(initialState: (() => S) | S)
{ const dispatcher = resolveDispatcher(); return dispatcher.useState(initialState); } @jwworth 40 -
// packages/react/src/ReactHooks.js export function useState<S>(initialState: (() => S) | S)
{ const dispatcher = resolveDispatcher(); return dispatcher.useState(initialState); // } @jwworth 42 -
"[T]he base class setState() implementation has been an illusion all
along. It doesn't do anything except forwarding the call to the current renderer. And [the] useState Hook does exactly the same thing." — Dan Abramov5 5 Abramov "How Does setState Know What to Do?" 2018. @jwworth 43 -
// packages/react/src/ReactHooks.js import ReactCurrentDispatcher from './ReactCurrentDispatcher'; function resolveDispatcher() { const
dispatcher = ReactCurrentDispatcher.current; return dispatcher; } @jwworth 44 -
// packages/react/src/ReactCurrentDispatcher.js import type {Dispatcher} from 'react-reconciler/src/ReactFiberHooks'; const ReactCurrentDispatcher =
{ current: (null: null | Dispatcher), }; export default ReactCurrentDispatcher; @jwworth 45 -
> const immutable = { permanent: "don't update me" }
undefined > immutable["permanent"] = 'uh oh' 'uh oh' > immutable { permanent: 'uh oh' } @jwworth 46 -
// packages/react/src/ReactCurrentDispatcher.js import type {Dispatcher} from 'react-reconciler/src/ReactFiberHooks'; const ReactCurrentDispatcher =
{ current: (null: null | Dispatcher), // }; export default ReactCurrentDispatcher; @jwworth 47 -
"[T]he base class setState() implementation has been an illusion all
along. It doesn't do anything except forwarding the call to the current renderer." — Dan Abramov5 5 Abramov "How Does setState Know What to Do?" 2018. @jwworth 48 -
// packages/react-dom/src/server/ReactPartialRenderer.js import { Dispatcher, } from './ReactPartialRendererHooks'; ReactCurrentDispatcher =
ReactSharedInternals.ReactCurrentDispatcher; ReactCurrentDispatcher.current = Dispatcher; @jwworth 49 -
// packages/react-dom/src/server/ReactPartialRendererHooks.js export function useState<S>( initialState: (() => S) |
S, ): [S, Dispatch<BasicStateAction<S>>] { return useReducer(basicStateReducer, (initialState: any)); } export const Dispatcher: DispatcherType = { useState, }; @jwworth 51 -
// packages/react-dom/src/server/ReactPartialRendererHooks.js // useReducer (abridged) workInProgressHook = createWorkInProgressHook(); workInProgressHook.memoizedState =
state; const dispatch: Dispatch<A> = (queue.dispatch: any); return [workInProgressHook.memoizedState, dispatch]; @jwworth 52 -
// packages/react-dom/src/server/ReactPartialRendererHooks.js function createHook(): Hook { return { memoizedState: null,
queue: null, next: null, }; } @jwworth 53 -
// Our code const [cannonscount, setCannonsCount] = useState(0); ‑ const
[WIPHookMemoizedState, dispatch] = useState(0); @jwworth 55 -
State Hooks Deep-Dive: Resurfacing » React checks types and creates
an interface for a dispatcher » The renderer nullifies and sets a real dispatcher » The dispatcher returns an array of memoized state and a setter function » Rendering and reconciliation occurs @jwworth 56 -
Further Reading » "RFC: React Hooks", Reactjs RFCs, accessed September,
2019, https://github.com/reactjs/rfcs/pull/68. » Abramov, Dan. 2018. "How Does setState Know What to Do?". Overreacted.io, December 9, 2018. https://overreacted.io/how-does-setstate-know-what-to-do/. » Abramov, Dan. 2018. "Why Do We Write super(props)?". Overreacted.io, November 30, 2018. https://overreacted.io/why-do-we-write-super-props/. » Albert, Sophie. 2015. "React v0.14". React.js Blog, October 7, 2015. https://reactjs.org/blog/2015/10/07/react-v0.14.html. » Alpert, Sophie. 2015. "React's Package Split". React.js Blog. July 3, 2015. https://reactjs.org/blog/2015/07/03/react-v0.14-beta-1.html#two-packages. » Clark, Andrew. 2016. "React Fiber Architecture". GitHub Gist. July 18, 2016. https://github.com/acdlite/react-fiber-architecture/blob/master/README.md. » Clark, Lin. 2017. "A Cartoon Intro to Fiber". Filmed at React Conf 2017, San Francisco, CA. Video. https://youtu.be/ZCuYPiUIONs. » Cowan, Paul. 2019. "Frustrations With Hooks". LogRocket Blog, September 9, 2019. https://blog.logrocket.com/frustrations-with-react-hooks/. » Dhuyvetters, Geoffrey. 2016. "What is React Fiber? And how can I try it out today?". GitHub Gist, December 20, 2016. https://gist.github.com/duivvv/2ba00d413b8ff7bc1fa5a2e51c61ba43. » Ehrenberg, Daniel and Morrison, Jeff. "Class field declarations for JavaScript". ECMT TC39, accessed September, 2019, https://github.com/tc39/proposal-class-fields. » Ferriss, Tim. 2016. Tools of Titans: The Tactics, Routines, and Habits of Billionaires, Icons, and World-Class Performers . New York: Houghton Mifflin Harcourt. » Giamir Buoncristiani, Giamir. 2017. "What is React Fiber?". Giamir.com. April 23, 2017. https://giamir.com/what-is-react-fiber. » Iffland, David. 2017. "React Fiber: A Closer Look at the New Engine of React". May 1, 2017. https://www.infoq.com/news/2017/05/react-fiber-closer-look/. » Markbåge, Sebastian. 2015. "React v0.13.0 Beta 1". React.js Blog. January, 2015. https://reactjs.org/blog/2015/01/27/react-v0.13.0-beta-1.html. » McCracken, Harry. 2014. "This 1981 Computer Magazine Cover Explains Why We're So Bad at Tech Predictions". Time Magazine, April 14, 2014, https://time.com/60505/this-1981-computer-magazine- cover-explains-why-were-so-bad-at-tech-predictions/. » Rouse, Margaret. s.v. "stateless". Whatis.com. Accessed September, 2019, https://whatis.techtarget.com/definition/stateless. » Flow Documentation, s.v. "Generics", accessed September 2019, https://flow.org/en/docs/types/generics/. » Flow Documentation, s.v. "Importing and Exporting Types", accessed September 2019, https://flow.org/en/docs/types/modules/#importing-and-exporting-types-. » Flow Documentation, s.v. "Type Aliases", accessed September 2019, https://flow.org/en/docs/types/aliases/. » Wikipedia, s.v. "Imperative Programming", accessed September 2019, https://en.wikipedia.org/wiki/Imperative_programming. @jwworth 66