There's no hook emoji… croissants look like hooks, right?
Mmmm… croissants with some sort of nut cream filling. Get it, hooks in a nutshell? Ha
Maybe I'm hungry 🤔
So anyway, React hooks took the React world by storm this weekend. They're not even out yet! And yet here we are.
JavaScript lyfe: New thing comes out, rocks the world, everyone says it's the next best thing since jQuery and will definitely make all your code better and all your knowledge obsolete. Time to learn stuff!
Untrue.
React hooks are neat. They look useful. They don't deprecate anything. Please don't rewrite your apps in hooks. Yet.
I watched Ryan's talk 90% cleaner with hooks last night, Dan's and Sophie's talk announcing hooks this morning, read all the docs, and watched Twitter like a disinterested hawk all weekend.
Hours of research condensed into the next 200 words because I love you. ❤️
Here's what you need to know about hooks right now 👇
You can try them out.
create-react-app look-ma-no-classes
- Open package.json, change
react
andreact-dom
tonext
yarn install
Hooks exist to rid your codebase of classes. Because classes are confusing to both people and compilers.
Where you used to class, you can now hook. In your functional components.
Built-in hooks cover the most common uses cases. You can build your own for everything else.
useState
The useState
hook replaces pairs of state getters and setters.
class myComponent extends React.Component {
state = {
value: 'default'
}
handleChange = (e) => this.setState({
value: e.target.value
})
render() {
const { value } = this.state;
return <input value={value} onchange={handleChange}>
}
}
👇
const myComponent = () => {
const [value, setValue] = useState('default');
const handleChange = (e) => setValue(e.target.value)
return <input value={value} onchange={handleChange}>
}
Less code to write and understand.
In a class component, you:
- set a default value
- create an
onChange
callback that firessetState
- read value from state before rendering etc.
Without modern fat arrow syntax, you might run into trouble with binds.
The hook approach moves that boilerplate to React's plate. You call useState
. It takes a default value and returns a getter and a setter.
You call that setter in your change handler.
Behind the scenes, React subscribed your component to that change. Your component re-renders.
useEffect
useEffect
replaces the componentDidMount
, componentDidUpdate
, shouldComponentUpdate
, componentWillUnmount
quadfecta. It's like a trifecta, but four.
Say you want a side-effect when your component updates, like make an API call. Gotta run it on mount and update. Want to subscribe to a DOM event? Gotta unsubscribe on unmount.
Wanna do all this only when certain props change? Gotta check for that.
Class:
class myComp extends Component {
state = {
value: 'default'
}
handleChange = (e) => this.setState({
value: e.target.value
})
saveValue = () => fetch('/my/endpoint', {
method: 'POST'
body: this.state.value
})
componentDidMount() {
this.saveValue();
}
componentDidUpdate(prevProps, prevState) {
if (prevState.value !== this.state.value) {
this.saveValue()
}
}
render() {
const { value } = this.state;
return <input value={value} onchange={handleChange}>
}
}
👇
const myComponent = () => {
const [value, setValue] = useState('default');
const handleChange = (e) => setValue(e.target.value)
const saveValue = () => fetch('/my/endpoint', {
method: 'POST'
body: this.state.value
})
useEffect(saveValue, [value]);
return <input value={value} onchange={handleChange}>
}
So much less code!
useEffect
runs your function on componentDidMount
and componentDidUpdate
. And that second argument, the [value]
part, tells it to run only when that value changes.
No need to double check with a conditional. If your effect updates the component itself through a state setter, the second argument acts as a shouldComponentUpdate
of sorts.
When you return a method from useEffect
, it acts as a componentWillUnmount
. Listening to, say, your mouse position looks like this:
const [mouseX, setMouseX] = useState()
const handleMouse = (e) => setMouseX(e.screenX)
useEffect(() => {
window.addEventListener("mousemove", handleMouse)
return () => window.removeEventListener(handleMouse)
})
Neat 👌
Waiting for the day we can use this to do naughty DOM stuff in functional components. Limiting factor right now is that we can't have refs I think.
useContext
useContext
cleans up your render prop callbacky hell.
<somecontext>
{state => ...}
</somecontext>
👇
const state = useContext(SomeContext)
Context becomes just a value in your function. React auto subscribes you to all updates.
useReducer
useReducer
is like React got Redux built in now. Whoa.
You don't really have to know this one. But it comes by default and it's kinda neat. Although I think using it for realz will lead to your components becoming way too big and bloated.
You should watch Ryan's talk to learn more about this one. Too long to explain in a nutshell 🥐 post.
So?
Will hooks change the way you write React forever? We'll see. The internet is excited.
You can write your own hooks. Repositories of hooks are popping up like crazy. I'm sure your internet will be full of them for the next while.
Most importantly 👇
You can write your own hooks and re-use functionality between components. It's just a function.
Dan and Sophie say this is the future of React. All functional. No classes.
But right now, it's just a Request For Comments. So comment away.
Continue reading about React hooks in a nut shell 🥐
Semantically similar articles hand-picked by GPT-4
- Custom react hooks ❤️
- useReducer + useContext for easy global state without libraries
- How to use React Context effectively
- Delightful state management with hooks and Constate
- Livecoding #25: Adding MobX to a vanilla React project
Learned something new?
Read more Software Engineering Lessons from Production
I write articles with real insight into the career and skills of a modern software engineer. "Raw and honest from the heart!" as one reader described them. Fueled by lessons learned over 20 years of building production code for side-projects, small businesses, and hyper growth startups. Both successful and not.
Subscribe below 👇
Software Engineering Lessons from Production
Join Swizec's Newsletter and get insightful emails 💌 on mindsets, tactics, and technical skills for your career. Real lessons from building production software. No bullshit.
"Man, love your simple writing! Yours is the only newsletter I open and only blog that I give a fuck to read & scroll till the end. And wow always take away lessons with me. Inspiring! And very relatable. 👌"
Have a burning question that you think I can answer? Hit me up on twitter and I'll do my best.
Who am I and who do I help? I'm Swizec Teller and I turn coders into engineers with "Raw and honest from the heart!" writing. No bullshit. Real insights into the career and skills of a modern software engineer.
Want to become a true senior engineer? Take ownership, have autonomy, and be a force multiplier on your team. The Senior Engineer Mindset ebook can help 👉 swizec.com/senior-mindset. These are the shifts in mindset that unlocked my career.
Curious about Serverless and the modern backend? Check out Serverless Handbook, for frontend engineers 👉 ServerlessHandbook.dev
Want to Stop copy pasting D3 examples and create data visualizations of your own? Learn how to build scalable dataviz React components your whole team can understand with React for Data Visualization
Want to get my best emails on JavaScript, React, Serverless, Fullstack Web, or Indie Hacking? Check out swizec.com/collections
Did someone amazing share this letter with you? Wonderful! You can sign up for my weekly letters for software engineers on their path to greatness, here: swizec.com/blog
Want to brush up on your modern JavaScript syntax? Check out my interactive cheatsheet: es6cheatsheet.com
By the way, just in case no one has told you it yet today: I love and appreciate you for who you are ❤️