1. 什么是Hooks?
Hooks的中文翻译为“钩子”。在React中,函数式组件写法简单,好理解,符合Js逻辑,类组件写起来比较复杂。但是函数式组件存在无状态、无生命周期的问题,Hooks可以让函数式组件拥有状态和生命周期。常用的Hooks有useState、useEffect、useContext。
2. useState
中文直译为“使用状态”,使用useState后,函数式组件也可以拥有状态。useState的返回结果是一个数组,数组的第一项是传入的初始数据,数组的第二项是更新初始数据的一个函数。一般通过解构赋值来保存useState的返回结果。
2.1 示例1
import React, {useState} from 'react'
export default function Hooks() {
// 解构赋值保存useState的结果
const [a,setA] = useState(0)
const [age,setAge] = useState(18)
const [hobby,setHobby] = useState("打篮球")
const [color,setColor] = useState("red")
return (
<div>
<h1 style={{color}}>{a}</h1>
<h1>年龄是:{age}</h1>
<h1>爱好是:{hobby}</h1>
<button onClick={()=>setColor("blue")}>改颜色</button>
<button onClick={()=>setAge(age+1)}>增加年龄</button>
<button onClick={()=>setHobby("踢足球")}>改爱好</button>
</div>
)
}
效果
点击“改颜色”按钮,数字0由红色变为蓝色;
点击“增加年龄”按钮,每点击一次,年龄增加1;
点击“改爱好”按钮,爱好由打篮球变为踢足球。
2.2 示例2
使用Hooks完成两个组件间的条件渲染。
import React,{useState} from 'react'
// 登录组件
function Login(){
return <h1>Login</h1>
}
// 注册组件
function Register(){
return <h1>Register</h1>
}
export default function Hello() {
const [ui,setUI] = useState("Login")
const onClickLogin=()=>{
setUI("Login")
}
const onClickRegister=()=>{
setUI("Register")
}
const showUI=()=>{
if(ui=="Login"){
return <Login/>
}else{
return <Register/>
}
}
return (
<div>
<button onClick={onClickLogin}>Login</button>
<button onClick={onClickRegister}>Register</button>
<div>
{showUI()}
</div>
</div>
)
}
效果
点击"Login"按钮,渲染登录组件;
点击"Register"按钮,渲染注册组件。
3. useEffect
useEffect可以解决函数式组件没有生命周期的问题。useEffect接收一个函数当参数。useEffect中包括componentDidMount(组件挂载)、componentDidUpdate(组件更新)、componentWillUnmount(组件卸载)。render函数中执行的是组件卸载。useEffect默认监测所有数据。
import React, {useState,useEffect} from 'react'
export default function Hooks() {
const [age,setAge]=useState(18)
useEffect(()=>{
console.log("组件更新")
return ()=>{
console.log("组件卸载")
}
})
return (
<div>
<h1>年龄:{age}</h1>
<button onClick={()=>setAge(age+1)}>增加年龄</button>
</div>
)
}
效果
4. useContext
useContext用来解决组件间传值,redux也可以用来完成组件间传值,但是useContext更简单。父组件中使用createContext创建传值的环境,在子组件和孙子组件中使用useContext接收父组件传过来的数据。
4.1 父组件、子组件、孙子组件在一个文件的情况
import React from 'react'
import {useState,useContext,createContext} from "react"
const Context = createContext()
const {Provider} = Context
function GrandSon(){
const a = useContext(Context)
return(
<div>
<h1>我是孙子组件--{a}</h1>
</div>
)
}
function Child() {
const b = useContext(Context)
return(
<div>
<div>
<h1>我是子组件--{b}</h1>
<GrandSon/>
</div>
</div>
)
}
export default function Parent(){
const [count,setCount]=useState("父组件的数据");
return(
<div>
<div>
<h1>我是父组件</h1>
<Provider value={count}>
<Child></Child>
</Provider>
</div>
</div>
)
}
效果
子组件和孙子组件能够拿到父组件中的数据
4.2 父组件、子组件、孙子组件在不同的文件
在实际情况中,父组件、子组件、孙子组件一般都在不同的文件中。这时需要建立一个单独的文件context.js来保存共同使用的传值环境。
contex.js文件
import { createContext } from "react";
const Context = createContext()
export default Context
父组件
import React, {useState} from "react"
import Child from "./Child"
import Context from './context'
const {Provider} = Context
export default function Parent(){
const [count,setCount]=useState("父组件的数据");
return(
<div>
<div>
<h1>我是父组件</h1>
<Provider value={count}>
<Child></Child>
</Provider>
</div>
</div>
)
}
子组件
import GrandSon from "./GrandSon"
import Context from "./context"
import { useContext } from "react"
export default function Child() {
const b = useContext(Context)
return(
<div>
<div>
<h1>我是子组件--{b}</h1>
<GrandSon/>
</div>
</div>
)
}
孙子组件
import Context from "./context"
import { useContext } from "react"
export default function GrandSon(){
const a = useContext(Context)
return(
<div>
<h1>我是孙子组件--{a}</h1>
</div>
)
}