Hooks:钩子,是React16.8中的新功能
Hooks作用:
1、组件的逻辑状态复用
(1)在Hooks之前,组件的状态逻辑复用经历了:mixins(混入)、HOCs(高阶组件)、render-props等模式
(2)(早已废弃)mixins的问题:数据来源不清晰、命名冲突
(3)HOCs(高阶组件)、render-props的问题:重构组件结构,导致组件形成jsx嵌套地狱问题
2、class组件自身问题
(1)选择:函数组件和class组件之间的区别以及使用
(2)需要理解class中的this是如何工作的
(3)互相关联且需要对照修改的代码被拆分到不同生命周期函数中
相比于函数组件来说,不利于代码压缩和优化,也不利于ts的类型推导
Hooks渐进式使用
class组件相关的API在hooks中可以不用
(1)class自身语法,比如,constructor、static
(2)钩子函数,componentDidMount、componentDidUpdate、componentWillUnmount
(3)this相关语法
class继续使用的语法
(1)JSX:{},onClick(),条件渲染、列表渲染、样式处理
(2)组件:函数组件、组件通讯
(3)React开发理念:单向数据流、状态提升
useState基本使用
1、使用useState为函数组件提供状态
2、内容:
(1)一个hook就是一个特殊的函数,让函数组件中获取状态等react特性.从名称上来看hook都以use开头
(2)useState的使用场景:当想要的函数组件中,使用组件状态时,就要使用useState Hook了
(3)useState作用:为函数组件提供状态
(4)参数:状态初始值
(5)返回值:stateArray是一个数组
import { useState } from 'react'
const Parent = () => {
// // 调用useState hook创建状态
// // const stateArray=useState(10)
// const stateArray=useState(10)
// // 拿到state状态
// const state=stateArray[0]
// // 拿到修改状态的函数
// const setState=stateArray[1]
const [state, setState] = useState(10)
const [user, setUser] = useState({ name: 'ii', age: 99 })
return (
<>
我是parent组件,我在试验useState属性的使用
<span>{state}</span>
<button onClick={() => setState(state + 1)}>点击</button>
<br />
<p>{user.name}</p>
<p>{user.age}</p>
<button onClick={() => setUser({ ...user, age: 55 })}>点击</button>
<button onClick={() => setUser({ name: 'uu', age: 55 })}>点击</button>
</>
)
}
export default Parent
3、useState是进行覆盖的操作
4、组件渲染规则
4.1组件第一次渲染
(1)从头开始执行该组件中的代码逻辑
(2)调用useState(0)将传入的参数作为状态初始值,即:0
(3)渲染组件时,获取到的数据状态是初始值0
4.2组件第二次渲染
(1)点击按钮,调用setCount(count+1)修改状态,因为状态发生改变,所以,该组件会重新渲染
(2)组件重新渲染时,会再执行该组件的代码逻辑
(3)再次调用useState(0),此时React内部会拿到最新的状态而非初始值,比如,该案例中最新的状态值是1
(4)再次渲染组件,此时,获取到的状态count值为1
4.3注意
useState的初始值指挥在第一次渲染组件时生效
useEffect副作用介绍
1、副作用定义:在计算机中,如果一个函数或其他操作修改了局部环境之外的状态变量值,那么他就被称为有副作用。
对于React组件来说,主作用就是根据数据渲染UI,除此之外都是副作用(比如,手动修改DOM)
常见副作用:ajax请求,手动修改DOM,localStorage,console.log操作
2、useEffect第二个参数:表示effect的依赖项
只有数组中的依赖项改变时effect回调才会执行
import {useState,useEffect } from "react";
const Parent =()=>{
const [user,setUser]=useState({name:'oo',age:66})
const [count,setCount]=useState(0)
// useEffect用法一
useEffect(()=>{
document.title='yyyy'
})
// useEffect用法二
useEffect(()=>{
localStorage.setItem('setUser','hooks')
})
// useEffect带第二个参数的用法
useEffect(()=>{
document.title=`${count}次被点击`
},[count])
return (
<>
我是parent组件
<p>{user.name}</p>
<button onClick={()=>setUser({...user,name:'yyyy'})}>点击</button>
<br />
<p>{count}</p>
<button onClick={()=>setCount(count+1)}>点击</button>
</>
)
}
export default Parent
3、useEffect解绑事件监听
useEffect(()=>{
const onReize=()=>{
console.log('onresize');
}
window.addEventListener('resize',onReize)
// 1、使用effect回调函数的返回值,来执行清理监听事件操作
return ()=>{
window.removeEventListener('resize',onReize)
}
},[count])
4、useEffect中发起异步请求
// useEffect不能有异步请求,所以需要在里面自定义异步函数并调用
useEffect(()=>{
const loadData=async()=>{
console.log('loadData');
}
loadData()
})
5、effect对依赖项撒谎
如果 useEffect 回调函数中用到了某个数据,但是,没有出现在依赖项数组中,就会导致一些 Bug 出现
useContext
一、回顾context
1、作用:实现跨组件传递数据,而不必在每个级别手动传递props,简化组件之间得数据传递过程
2、context对象包含了两个组件
<Context.Provider value>:通过value属性提供数据
<Context.Consumer>:通过render-props模式,在JSX中获取Context中提供数据
3、默认值
提供默认值时需要让默认值得结构与Provider提供得value值结构保持一致
默认值生效得时机:当在使用Context对象得时候,如果没有提供Provider,此时得默认值生效
1
import { createContext, useState } from "react";
const ColorContext = createContext({
color: "red",
setColor: () => {},
});
const List = ({ children }) => {
return (
3
<ColorContext.Consumer>
{(value) => (
<>
<p>list组件{value.color}</p>
<p>{children}</p>
<button onClick={() => value.setColor("blue")}>
点击修改color数据
</button>
</>
)}
</ColorContext.Consumer>
);
};
const Child = () => {
return <List>我是child传过来的</List>;
};
const Parent = () => {
const [color, setColor] = useState("green");
console.log(color);
return (
<>
{/* 2 */}
<ColorContext.Provider value={{ color, setColor }}>
<p>{color}</p>
<Child></Child>
</ColorContext.Provider>
</>
);
};
export default Parent;
二、useContext
和context区别:获取位置不同,context只能在JSX中获取。useContext可以在JS和JSX中获取。
/第一步:书写公共引入样式
import { createContext, useContext, useState } from "react";
const ColorContext = createContext();
const List = () => {
/第三步:使用useContext接收传入的参数
const { color, setColor } = useContext(ColorContext);
console.log(color);
return (
<>
<p>我是list组件---{+color}</p>
{/* /第四步:使用数据 */}
<button onClick={() => setColor(!color)}>点击改变color</button>
</>
);
};
const Child = () => {
return (
<>
<List></List>
<p>我是child组件</p>
</>
);
};
const Parent = () => {
const [color, setColor] = useState(true);
return (
<>
{/* /第二步:提供传入的参数 */}
<ColorContext.Provider value={{ color, setColor }}>
<Child></Child>
</ColorContext.Provider>
<p>我是parent组件</p>
</>
);
};
export default Parent;
useRef
使用场景:在React中进行DOM操作,用来获取DOM。
作用:返回一个带有current属性的可变对象,通过该对象就可以进行DOM操作了。
import { useRef } from "react"
const Parent=()=>{
/第一步:使用useRef创建一个ref对象
const inputRef=useRef(null)
const add=()=>{
/第三步:通过inputRef.current来访问对应的DOM
console.log(inputRef.current.value);
inputRef.current.focus()
}
return (
<>
<div>useRef的使用</div>
{/* /第二步:将ref对象设置为input的ref属性值,
目的:将ref对象关联到input对应的DOM对象身上 */}
<input type="text" placeholder="请输入内容" ref={inputRef}/>
<button onClick={add}>点击</button>
</>
)
}
export default Parent