❓ If you don’t already know, check out this article to see the differences and usages between three basic Hooks and traditional class components 😙
The three basic Hooks we refer to are:
useState
Maintenance within functional componentsstate
useEffect
Functional components have side effects called andcomponentDidMount
,componentDidUpdate
Similar but differentuseContext
Listen for changes to the provider
useState
UseState allows us to maintain state in functional components that traditionally would have required class components. For example, 🌰, we need an input box, and as the content of the input box changes, so does the content of the label label inside the component. Here are two different ways to write it:
Not using useState:
import React from "react";
/ / 1
export class ClassTest extends React.Component {
/ / 2
state = {
username: this.props.initialState
}
/ / 3
changeUserName(val) {
this.setState({ username: val })
}
/ / 4
render() {
return (
<div>
<label style={{ display: 'block'}}htmlFor="username">username: {this.state.username}</label>
<input type="text" name="username" onChange={e= > this.changeUserName(e.target.value)} />
</div>)}}Copy the code
- We need to define a class from
React.Component
inherit - We need to initialize one more
state
- Initialization change
state
The method of - And the last thing I want to do is use
render
The function returnsJSX
✅ Use useState:
/ / 1
import React, { useState } from "react";
export function UseStateTest({ initialState }) {
/ / 2
let [username, changeUserName] = useState(initialState)
/ / 3
return (
<div>
<label style={{ display: 'block'}}htmlFor="username">username: {username}</label>
<input type="text" name="username" onChange={e= > changeUserName(e.target.value)} />
</div>)}Copy the code
Used in the parent component:
import React from "react";
// Import components
import { UseStateTest } from './components/UseStateTest'
/ / 4
const App = (a)= > (
<div>
<UseStateTest initialState={'initial value'} / >
</div>
)
export default App;
Copy the code
- Need from
react
The introduction ofuseState
The 📦 - use
useState
Method that receives an initialization parameter, definedstate
Variables, and changesstate
The method of - Use it directly where it is needed
state
This variable can be added to the event handler to trigger the changestate
The method of - Called in the parent component, through
props
passinitialState
The initialization value
Replacing the class with the useState method not only improves performance, but you can also see a lot less code and no longer need to use this, so functional components that can maintain state are really nice 😀
class classTest extends React.Components {}
🔜function UseStateTest(props) {}
Functional component writingthis.state.username
🔜username
usestate
Don’t needthis
this.setState({ username: '' })
🔜changeUserName('')
changestate
You don’t have to writesetState
methods
Documentation: https://zh-hans.reactjs.org/docs/hooks-state.html
useEffect
UseEffect is specifically designed to handle side effects, such as getting data, creating subscriptions, manually changing the DOM, and so on. You can imagine it’s a combination of componentDidMount and componentDidUpdate and componentWillUnmount.
For example 🌰🌰, let’s say we create a div tag that sends an HTTP request every time it is clicked and changes the page title to the corresponding value:
import React from 'react'
/ / 1
import { useState, useEffect } from 'react'
export function UseEffectTest() {
let [msg, changeMsg] = useState('loading... ')
/ / 2
async function getData(url) { // Get json data
return await fetch(url).then(d= > d.json())
}
/ / 3
async function handleClick() { // Click the event to change state
let data = await getData('https://httpbin.org/uuid').then(d= > d.uuid)
changeMsg(data)
}
/ / 4
useEffect((a)= > { / / side effects
document.title = msg
})
return (
<div onClick={()= > handleClick()}>{msg}</div>)}Copy the code
- First of all, from the
react
The introduction ofuseEffect
😳 - Then create one that gets the data
getData
methods - Create an event handler
handleClick
- use
useEffect
Dealing with side effects: changes to the pagetitle
If you use the traditional way of writing class components:
import React from 'react'
/ / 1
export class ClassTest extends React.Component {
/ / 2
state = {
msg: 'loading... '
}
/ / 3
async getData(url) { // Get json data
return await fetch(url).then(d= > d.json())
}
handleClick = async() = > {// Click the event to change state
let data = await this.getData('https://httpbin.org/uuid').then(d= > d.uuid)
this.setState({ msg: data })
}
/ / 4
componentDidMount() {
document.title = this.state.msg
}
componentDidUpdate() {
document.title = this.state.msg
}
/ / 5
render() {
return (
<div onClick={this.handleClick}>{this.state.msg}</div>)}}Copy the code
- First create the class
ClassTest
- Initialize the
state
- Define methods for getting data and event handlers
- in
componentDidMount
和componentDidUpdate
Phase changedocument.title
- At last,
render
Function to render
This pile of things to write people are asleep 💤
UseEffect not only removes some of the unnecessary stuff, but also incorporates the componentDidMount and componentDidUpdate methods, where the code only needs to be written once. 😀
This hook fires after the first rendering and every update, if you need to manually modify the custom trigger rules
See documentation: https://zh-hans.reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects
In addition, the website also provides an example of subscribing to clear subscriptions:
Use useEffect to return a function directly:
The function returned is optional and may or may not be used:
Documents: https://zh-hans.reactjs.org/docs/hooks-effect.html#recap
For example, we use useEffect to unbind event handlers:
useEffect((a)= > {
window.addEventListener('keydown', handleKeydown);
return (a)= > {
window.removeEventListener('keydown', handleKeydown); }})Copy the code
useContext
One of the biggest changes to useContext is that we don’t need to wrap Children around Consumer. For example, we create a context that has a state called username. And a method to modify username, handleChangeUsername
Create context
Not using useState:
This code does not use state hooks:
import React, { createContext } from 'react'
// 1. Create the context using createContext
export const UserContext = new createContext()
// 2. Create Provider
export class UserProvider extends React.Component {
handleChangeUsername = (val) = > {
this.setState({ username: val })
}
state = {
username: ' '.handleChangeUsername: this.handleChangeUsername
}
render() {
return (
<UserContext.Provider value={this.state}>
{this.props.children}
</UserContext.Provider>Create Consumer export const UserConsumer = userContext.consumerCopy the code
Look what we did:
- First we use
createContext
Create context - And then we create
Provider
; It defineshandleChangeUsername
Methods andusername
的state
And returns a packagethis.props.children
的Provider
- And then we’ll come back
UserContext.Consumer
The code is verbose and can be simplified using useState, as mentioned above:
✅ Use useState:
Use state hooks:
import React, { createContext, useState } from 'react'
// 1. Create the context using createContext
export const UserContext = new createContext()
// 2. Create Provider
export const UserProvider = props= > {
let [username, handleChangeUsername] = useState(' ')
return (
<UserContext.Provider value={{username, handleChangeUsername}} >
{props.children}
</UserContext.Provider>} // 3. Create Consumer export const UserConsumer = userContext.consumerCopy the code
Using useState to create context is much more concise.
Use context
Once the context is defined, let’s look at the difference between using useContext and not using useContext 🎁 :
Without useContext:
import React from "react";
import { UserConsumer, UserProvider } from './UserContext'
const Pannel = (a)= > (
<UserConsumer>} {({username, handleChangeUsername}) => (<div>
<div>user: {username}</div>
<input onChange={e= > handleChangeUsername(e.target.value)} />
</div>
)}
</UserConsumer>
)
const Form = () => <Pannel></Pannel>
const App = () => (
<div>
<UserProvider>
<Form></Form>
</UserProvider>
</div>
)
export default App;
Copy the code
✅ Using useContext:
Just import the UserContext and use the useContext method:
import React, { useContext } from "react"; / / 1
import { UserProvider, UserContext } from './UserContext' / / 2
const Pannel = (a)= > {
const { username, handleChangeUsername } = useContext(UserContext) / / 3
return (
<div>
<div>user: {username}</div>
<input onChange={e= > handleChangeUsername(e.target.value)} />
</div>
)
}
const Form = () => <Pannel></Pannel>
// 4
const App = () => (
<div>
<UserProvider>
<Form></Form>
</UserProvider>
</div>
)
export default App;
Copy the code
Here’s what it does:
- So the first step is to introduce
useContext
- Then introduce the
UserProvider
And contextUserContext
- Call from the component you want to use
useContext
Methods to obtainstate
- Of course, if used in the parent component
UserProvider
Nested masterchildren
This completes the refactoring with useContext and useState, and looks like a lot less code 😄
That’s it. Functional components that work with Hooks are really cool ⛄
Reference:
- https://codeburst.io/quick-intro-to-react-hooks-6dd8ecb898ed
- https://reactjs.org/docs/hooks-reference.html