React 16.8.0 is the first release to support Hooks. When upgrading, don’t forget to update all packages, including React DOM. React Native will support Hooks in the next stable release.
why ?
It’s hard to reuse stateful logic between components:
render props、higher-order components: restructure your components
With Hooks, you can extract stateful logic from a component so it can be tested independently and reused.
Hooks allow you to reuse stateful logic without changing your component hierarchy.
Hooks let you split one component into smaller functions based on what pieces are related (such as setting up a subscription or fetching data),
Classes confuse both people and machines
Hooks let you use more of React’s features without classes.
React components have always been closer to functions.
Hooks embrace functions, but without sacrificing the practical spirit of React.
how to do?
Hooks work side-by-side with existing code so you can adopt them gradually.
we will keep supporting class components for the foreseeable future.
Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.
State Hook
初识
// We import the useState Hook from React. It lets us keep local state in a function component.
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
/* // 数组解构
var fruitStateVariable = useState('banana'); // Returns a pair
var fruit = fruitStateVariable[0]; // First item in a pair
var setFruit = fruitStateVariable[1]; // Second item in a pair
*/
return (
<div>
<p>You clicked {count} times</p>
// When the user clicks, we call setCount with a new value. React will then re-render the Example component, passing the new count value to it.
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
useState is a Hook;
useState returns a pair: the current state value and a function that lets you update it.
// function components
const Example = (props) => {
// You can use Hooks here!
return <div />;
}
// or
function Example(props) {
// You can use Hooks here!
return <div />;
}
Hooks don’t work inside classes. But you can use them instead of writing classes.
What’s a Hook?
A Hook is a special function that lets you “hook into” React features.
e.g. : useState is a Hook that lets you add React state to function components.
If you write a function component and realize you need to add some state to it, previously you had to convert it to a class.
Now you can use a Hook inside the existing function component.
Declaring a State Variable
// in class components
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
// useState in hooks, in a function components
// In a function component, we have no this, so we can’t assign or read this.state. Instead, we call the useState Hook directly inside our component
// The only argument to the useState() Hook is the initial state.
// If we wanted to store two different values in state, we would call useState() twice.
// useState returns a pair of values: the current state and a function that updates it.
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
Reading State
// in a class
<p>You clicked {this.state.count} times</p>
// in a function
<p>You clicked {count} times</p>
Updating State
// in a class
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
// in a function
<button onClick={() => setCount(count + 1)}>
Click me
</button>
Effect Hook
useEffect,adds the ability to perform side effects from a function component.
Data fetching, setting up a subscription, and manually changing the DOM in React components are all examples of side effects.
It serves the same purpose as componentDidMount, componentDidUpdate, and componentWillUnmount in React classes, but unified into a single API.
Effects are declared inside the component so they have access to its props and state.
import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
// Update the document title using the browser API
document.title = `You clicked ${count} times`;
});
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Effects may also optionally specify how to “clean up” after them by returning a function.
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
// we have to duplicate the code between these two lifecycle methods in class.
// 其实这种操作是每次渲染之后都该做的,只是react class 组件没有这种方法。。。
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
// we have to duplicate the code between these two lifecycle methods in class.
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
Example Using Hooks
By using this Hook, you tell React that your component needs to do something after render.
React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates.
In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.
useEffect runs both after the first render and after every update.
Unlike componentDidMount or componentDidUpdate, effects scheduled with useEffect don’t block the browser from updating the screen.
Effects with Cleanup
For example, we might want to set up a subscription to some external data source. In that case, it is important to clean up so that we don’t introduce a memory leak!
code for adding and removing a subscription is so tightly related that useEffect is designed to keep it together.
If your effect returns a function, React will run it when it is time to clean up.
import React, { useState, useEffect } from 'react';
function FriendStatus(props) {
const [isOnline, setIsOnline] = useState(null);
useEffect(() => {
function handleStatusChange(status) {
setIsOnline(status.isOnline);
}
ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
// Specify how to clean up after this effect:
// This is the optional cleanup mechanism for effects.
return function cleanup() {
ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
};
});
if (isOnline === null) {
return 'Loading...';
}
return isOnline ? 'Online' : 'Offline';
}
When??
React performs the cleanup when the component unmounts.
effects run for every render and not just once.
This is why React also cleans up effects from the previous render before running the effects next time.
Why Effects Run on Each Update
componentDidMount() {
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
// status会改变,只有在update中不断侦听status,取消订阅、再次订阅才能满足需求;否则会异常。
componentDidUpdate(prevProps) {
// Unsubscribe from the previous friend.id
ChatAPI.unsubscribeFromFriendStatus(
prevProps.friend.id,
this.handleStatusChange
);
// Subscribe to the next friend.id
ChatAPI.subscribeToFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
componentWillUnmount() {
ChatAPI.unsubscribeFromFriendStatus(
this.props.friend.id,
this.handleStatusChange
);
}
React relies on the order in which Hooks are called。
// ------------
// First render
// ------------
useState('Mary') // 1. Initialize the name state variable with 'Mary'
useEffect(persistForm) // 2. Add an effect for persisting the form
useState('Poppins') // 3. Initialize the surname state variable with 'Poppins'
useEffect(updateTitle) // 4. Add an effect for updating the title
// -------------
// Second render
// -------------
useState('Mary') // 1. Read the name state variable (argument is ignored)
useEffect(persistForm) // 2. Replace the effect for persisting the form
useState('Poppins') // 3. Read the surname state variable (argument is ignored)
useEffect(updateTitle) // 4. Replace the effect for updating the title
// ...
bad
// 🔴 We're breaking the first rule by using a Hook in a condition
if (name !== '') {
useEffect(function persistForm() {
localStorage.setItem('formData', name);
});
}
so, 不要放在嵌套函数里,一定要放在top level上~可以用下边的方式判断~~不要破坏顺序。。
useEffect(function persistForm() {
// 👍 We're not breaking the first rule anymore
if (name !== '') {
localStorage.setItem('formData', name);
}
});
Hooks 约定俗成的一些东西:
Custom Hooks are more of a convention than a feature.
If a function’s name starts with ”use” and it calls other Hooks, we say it is a custom Hook.
可是如果以前代码中使用use打头,但又没有hooks功能呢??
The useSomething naming convention is how our linter plugin is able to find bugs in the code using Hooks.
Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.
Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.(不共享数据,之共享处理的逻辑)
Each call to a Hook gets isolated state. 其实我们在实现hook时,实用了useState 或者 useEffect,而这两个的调用都是相互独立的。
其他的Hooks-Hooks API
a few less commonly used built-in Hooks that you might find useful.
如:useContext lets you subscribe to React context without introducing nesting。
React Hooks
React 16.8、useState、
why ?
how to do?
Hooks 概览
State Hook
初识
useState is a Hook; useState returns a pair: the current state value and a function that lets you update it.
进阶
等价的 Class 例子
Hooks and Function Components
Hooks don’t work inside classes. But you can use them instead of writing classes.
What’s a Hook?
A Hook is a special function that lets you “hook into” React features. e.g. : useState is a Hook that lets you add React state to function components.
If you write a function component and realize you need to add some state to it, previously you had to convert it to a class. Now you can use a Hook inside the existing function component.
Declaring a State Variable
Reading State
Updating State
Effect Hook
useEffect,adds the ability to perform side effects from a function component.
Effects may also optionally specify how to “clean up” after them by returning a function.
多个effect 时,
Effects Without Cleanup
Example Using Classes
Example Using Hooks
Effects with Cleanup
For example, we might want to set up a subscription to some external data source. In that case, it is important to clean up so that we don’t introduce a memory leak!
Example Using Classes
Example Using Hooks
code for adding and removing a subscription is so tightly related that useEffect is designed to keep it together. If your effect returns a function, React will run it when it is time to clean up.
When?? React performs the cleanup when the component unmounts. effects run for every render and not just once. This is why React also cleans up effects from the previous render before running the effects next time.
Why Effects Run on Each Update
也因此,effect需要每次都重置。。 以下,可以省去很多代码,还规避了内存泄漏的问题。
Optimizing Performance by Skipping Effects
In some cases, cleaning up or applying the effect after every render might create a performance problem.
// 那如何防止频繁run effect 呢?
Hooks 规则
Hooks are JavaScript functions, but they impose two additional rules:
一个插件:linter plugin
ESLint Plugin
当声明多个state 或者 effect 时,react 是怎么知道他们对应哪个 useState 呢?
bad
so, 不要放在嵌套函数里,一定要放在top level上~可以用下边的方式判断~~不要破坏顺序。。
创建自己的Hooks
Hooks 约定俗成的一些东西: Custom Hooks are more of a convention than a feature. If a function’s name starts with ”use” and it calls other Hooks, we say it is a custom Hook.
The useSomething naming convention is how our linter plugin is able to find bugs in the code using Hooks.
Custom Hooks are a convention that naturally follows from the design of Hooks, rather than a React feature.
Custom Hooks are a mechanism to reuse stateful logic (such as setting up a subscription and remembering the current value), but every time you use a custom Hook, all state and effects inside of it are fully isolated.(不共享数据,之共享处理的逻辑)
Each call to a Hook gets isolated state. 其实我们在实现hook时,实用了useState 或者 useEffect,而这两个的调用都是相互独立的。
其他的Hooks-Hooks API
a few less commonly used built-in Hooks that you might find useful. 如:useContext lets you subscribe to React context without introducing nesting。
useReducer lets you manage local state of complex components with a reducer: