notes from Fun with React Hooks - Michael Jackson and Ryan Florence
the Michael Jackson part of the talk
##but first, go and watch it! i'll wait.
the number one feature of react hooks is composability
an "effect" in functional programming terms refers to "side" effects. if your function adds two numbers, its "main" effect is to add two numbers and return the result. it's side effect is anything else, like printing it to console, timestamping it, keeping track of the previously added numbers...
in react, useEffect() is the same (it refers to side effects, or things your component does that is out of sync with the initial render flow).
import React, { useState, useEffect } from "react";
import axios from "axios";const fetchSomething = async (query) => {
return await axios
.get(`http://hn.algolia.com/api/v1/search?query=${query}`)
.then((res) => {
return { result: res, error: false };
})
.catch((e) => {
return { result: null, error: true };
});
};// all the lifecycle methods needed to make sure your
// function fetches and doesn't leak memory
class User extends React.Component {
state = { user: null };
fetch() {
fetchSomething(this.props.query).then((res) => {
this.setState({ user: res.result });
});
}
componentDidMount() {
this.fetch();
}
componentDidUpdate(prevProps) {
if (this.props.query !== prevProps.query) {
if (!this.__isUnMounted) this.fetch();
}
}
componentWillUnmount() {
this.__isUnMounted = true;
}
render() {
// render props pattern, so send data to children
return this.props.children(this.state.user);
}
}const AppComponent = ({ query }) => {
return (
<User query={query}>
{user => {
return <p>{JSON.stringify(user)}</p>
}}
</User>
)
}this is where hooks come in. in particular, useEffect().
this is, in effect, item number 3.:
const AppHooks = ({ query }) => {
const [user, setUser] = useState(null)
useEffect(
() => {
let current = true
fetchSomething(query).then(res => {
if (current) setUser(res)
})
return () => {
current = false
}
},
[query]
)
return <p>{JSON.stringify(user)}</p>
}or more similarly:
// maybe put it in a file you import, or npm publish it, or whatever
const useUser = query => {
const [user, setUser] = useState(null)
useEffect(
() => {
let current = true
fetchSomething(query).then(res => {
if (current) setUser(res)
})
return () => {
current = false
}
},
[query]
)
return user
}
const AppHooks = ({ query }) => {
const user = useUser(query) // ... and then use it like this
return <p>{JSON.stringify(user)}</p>
}no more lifecycle methods.
useEffect() feels to me like the keystone to the hooks pattern, as it reduces boilerplate code while making your state management code composable.
it is the fact that you can take a chunk of related logic and put it in a function somewhere else, so that you can abstract away the complexity, while making it possible for your colleagues and other programmers to use your stateful component without having to resort to different (sometimes unintuitive) ways of passing around stateful data.
const AppHooks = ({ query }) => {
const [user, setUser] = useState(null)
useEffect(
() => {
let current = true
fetchSomething(query).then(res => {
if (current) setUser(res)
})
return () => {
current = false
}
},
[query]
)
return <p>{JSON.stringify(user)}</p>
}// maybe put it in a file you import, or npm publish it, or whatever
const useUser = query => {
const [user, setUser] = useState(null)
useEffect(
() => {
let current = true
fetchSomething(query).then(res => {
if (current) setUser(res)
})
return () => {
current = false
}
},
[query]
)
return user
}
const AppHooks = ({ query }) => {
const user = useUser(query) // ... and then use it like this
return <p>{JSON.stringify(user)}</p>
}####it allows you to rearrange multiple stateful components that depended on data from the each other:
const AppComponent = ({ query }) => {
return (
<User query={query}>
{(user) => {
return (
<>
<p>{JSON.stringify(user)}</p>
<UserDetails query={user}>
{(details) => {
return <p>{JSON.stringify(details)}</p>;
}}
</UserDetails>
</>
);
}}
</User>
);
};it starts to look a bit confusing (all the brackets!! where's the fetching part? and nobody likes pyramids (only one, he's the sun god so he can.)
####into this:
const AppHooks = ({ query }) => {
const user = useUser(query);
const details = useUserDetails(user);
return (
<>
<p>{JSON.stringify(user)}</p>
<p>{JSON.stringify(details)}</p>
</>
);
};making things composable frees up the programmer from having to follow some sort of arbitrary structure defined by a library that might not map to his/her mental model of the app he/she is building.
##it's like the react team made a better lego block.

