So, if you follow the react community right now, we are on fire !
Please welcome an incredible thing for functional components: hooks
What is a hook ?
Till now, we, react developpers, made the distinction between stateless components (functions) and stateful ones (classes).
With hooks, we got a set of primitive that will help us to interact with local state, side effects, ... for functional components.
This post is the first in a series that will cover the available react-hooks.
useState hook
Let's start with a very useful and easy one:
useState
Hooks are available from the 16.7.0-alpha.0
tag onward on npm, so you can run:
npm install --save react@16.7.0-alpha.0 react-dom@16.7.0-alpha.0
or use a online editor to test 'em:
(playground)[https://stackblitz.com/edit/react-avqzi1]
With this trivial example, we can demonstrate the main features of the useState hook:
import { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
When we call useState(initialValue: any)
, this will return an array of 2 elements:
- first the actual current value of the data
- second is a function that let you change the data.
At first the count is equal to 0, and each time we call setCount(count + 1), a rerender will occur !
If you ever used withState
from recompose, this is basically the same things except:
- this is much simpler to reason about
- you don't complexify your tree with another layer of indirection,
One thing to note is that the generated state is isolated. With Hooks we are able to reuse state logic and not state data.
So if you call again useState (or use generated useState from a custom hook [more of this later] ), you will refer to another data cell !
Concrete Application: Validation
The most interesting part is that I can generate a hook from another function that could be reused in differents components.
As useState is mapped to the 'rerendering' lifecycle of the component, we can reason about it very easily.
function setWithValidation(businessRule, setValidated, setData) {
// simple IOC
// create a new function that is able to set validated state and change the data value
return newValue => {
setValidated(businessRule(newValue))
setData(newValue)
}
}
function withValidation(businessRule) {
return initialData => {
// create an data cell for the main data we need
const [data, setData] = React.useState(initialData)
// create a data cell for the validation state
const [validated, setValidated] = React.useState(businessRule(initialData))
// return in a nice object, the data, a modified set function and the validated state
return {data, set: setWithValidation(businessRule, setValidated, setData), validated}
}
}
Now I have a flexible data cell that can validated !
The usage is trivial:
function isEven(value){ return value % 2 === 0}
const useEvenData = withValidation(isEven)
function Example() {
// Declare a new state variable, which we'll call "count"
const {data, validated, set} = useEvenData(0);
return (
<div>
<p>You clicked {data} times</p>
{validated ? <p>The number is even</p> : <p>The number is odd :-(</p> }
<button onClick={() => set(data + 1)}>
increment
</button>
<button onClick={() => set(data -1)}>
decrement
</button>
</div>
);
}
You can try it here:
Beware, you cannot use a hook outside a context of a component. Also place it at the top level of your component (not inside a loop, conditionnal...)
That's it ! Feel free to comment and see you in the part 2, with side effects hooks.
Links
https://reactjs.org/docs/hooks-intro.html
https://reactjs.org/docs/hooks-overview.html
Top comments (0)