State Management
in a World of Hooks
Adam Klein
Image by Kurt Deiner from Pixabay
React 0.X
Mixins
Mixins
const MouseMixin = {
getInitialState() {
return { x: 0, y: 0 }
},
handleMouseMove(event) {
this.setState({
x: event.clientX,
y: event.clientY
})
}
}
React 15+
Higher Order Components
Higher Order Component (HOC)
const AppWithLog = logProps(App);
Unwrapping our components
Wrapper Hell
React 15+
Render Props
Render Props
const App = () => (
<div>
<Mouse render={({ x, y }) => (
// The render prop gives us the state we need
// to render whatever we want here.
<h1>The mouse position is ({x}, {y})</h1>
)}/>
</div>
);
Render Props
const App = () => (
<div>
<Mouse render={({ x, y }) => (
// The render prop gives us the state we need
// to render whatever we want here.
<h1>The mouse position is ({x}, {y})</h1>
)}/>
</div>
);
const MyForm = () => (
<DataFetcher>
{( data ) => (
<Actions>
{( actions ) => (
<Translations>
{( translations ) => (
<Styles>
{(styles) => (
<form style={styles}>
<input type="text" value={data.value} />
<button onClick={action.submit}>
{ translations.submitText }
</button>
</form>
)}
</Styles>
)}
</Translations>
)}
</Actions>
)}
</DataFetcher>
);
React Conf 2018
Function StateHook = +
React
const App = () => {
const [isLoading, setIsLoading] = useState(false);
const [user, setUser] = useState({});
return (
<div style={{ height: '100%' }}>
Welcome { user }
<button onClick={() => setRole(ROLES.ADMIN)}>
Make Admin
</button>
</div>
);
};
const App = () => {
const [isLoading, setIsLoading] = useState(false);
const [user, setUser] = useState({});
return (
<div style={{ height: '100%' }}>
Welcome { user }
<button onClick={() => setRole(ROLES.ADMIN)}>
Make Admin
</button>
</div>
);
};
useState()
useState()
useEffect()
Component
useState()
useState()
useEffect()
Component
useState()
useState()
useEffect()
const useUser = () => {
const ROLES = { ADMIN: 'ADMIN', CLIENT: 'CLIENT' };
const [user, setUser] = useState(null);
const setAdmin = useCallback((role) => {
setUser({ ...user, role });
}, [user]);
return [user, setAdmin, ROLES];
};
Custom Hook
const useUser = () => {
const ROLES = { ADMIN: 'ADMIN', CLIENT: 'CLIENT' };
const [user, setUser] = useState(null);
const setAdmin = useCallback((role) => {
setUser({ ...user, role });
}, [user]);
return [user, setAdmin, ROLES];
};
Custom Hook
Credit:
https://twitter.com/prchdk
Sharing State
GIF Credit: https://www.youtube.com/channel/UCuC9HfR6o-tJPjxZEbWJeLQ
Lift State Up
Photo Credit: Max Ellis
Flux
React Context
Provider
State
React Context
Provider
State
React Context
Use Hooks
Share data between components
Avoid props drilling
React Context
Provider1(state1)
Provider2(state2)
Provider3(state3)
Provider4(state4)
Components
const App = () => (
<Layout>
<UsersProvider>
<Header />
</UsersProvider>
<AccountsProvider>
<AccountScreen />
</AccountsProvider>
<Footer />
</Layout>
);
Provider
State
Provider
State Where is my state? 😢
<StockProvider/>
Title
Price
<Headline/>
Render Bailout
<StockProvider/>
Title
Price
<Headline/>
What’s the title?
Render Bailout
<StockProvider/>
Title
Price
<Headline/>
Here’s the new price
What’s the title?
Render Bailout
<StockProvider/>
Title
Price
<Headline/>
Ummmm…. I just want the title
Render Bailout
Here’s the new price
<StockProvider/>
Title
Price
<Headline/>
Ummmm…. I just want the title
Render Bailout
Here’s the new price
StateProvider
State
Component
ActionsProvider
Actions
When Context isn't Enough
Global State Management
<App />
<Layout />
<Header /> <Accounts />
<User />
Store
Users Accounts
State Management React Component Tree
Direct Subscriptions
const App = () => {
const [user, userActions] = useUser();
return (
...
);
};
const App = ({ pageSize }) => {
const [user, userActions] = useUser();
const [posts] = usePosts(user.id, pageSize);
return (
...
);
};
Hooks
Redux
MobX
useState/useReducer
reducer + actions
@observable
State
useMemo
reselect
@computed
Computed
useEffect
middleware
autorun/reaction
Side Effects
Local/Context => State Management
Large refactor
What if we want it all?
Introducing
Reusable
Local State
Component 1
Local State
Component 2
Component 1
Custom Hook
Component 1
Component 2
Store
Component 1
Component 2
createStore( )
Store
Component 1
Component 2
createStore( )
I just want the title!
Store 1
Store 2
Store 1
Router Context
Store 2
Store 1
Router Context
Custom Hook
Store 2
Component 1
Store 1
Component 2
Package
Component 1
Component 2
Store 1
App 1
Package
Component 1
Component 2
Store 1
App 2
Live Demo
Global State Management
Using Hooks
https://github.com/reusablejs/reusable
Today’s legacy code is
yesterday’s most popular tool
Thank You
https://adamklein.dev
https://github.com/reusablejs/reusable
https://twitter.com/adamklein500

State managment in a world of hooks