一、useState
1.快速使用
import {useState} from "react";
/*
* useState
* 1.导入useState函数,
* 2.执行这个函数,并传入初始值 必须在函数组件中
* 3.【数据,修改数据的方法】
* 4.使用数据,修改数据
* */
function App() {
const [count, setCount] = useState(0)
return (
<div className="App">
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
</div>
);
}
export default App;
2.状态的读取和修改
/*
* 状态的读取和修改
* const [count, setCount] = useState(0)
* 1.useState传过来的参数 作为count的初始值
* 2.[count, setCount] 这里的写法是一个解构赋值 useState的返回值是一个数组
* 名字可以自定义吗? --> 可以自定义保持语义化
* 顺序可以换吗? --> 不可以 第一个参数就是数据的状态 第二个参数就是修改数据的方法
* 3.setCount函数,用来修改count 依旧保持不能直接修改原值 还是生成一个新值替换
* setCount(基于原值计算得到新值)
* 4.count和setCount是一对 是绑定在一起的 setCount只能用来修改对应的count值
* */
/*
* 当调用setCount的时候 更新过程
* 首次渲染
* 首次本渲染的时候 组件内部的代码会被执行一次
* 其中 useState 也会跟着执行,这里重点注意,初始值只在首次渲染时生效
*
* 更新渲染
* 1.app组件会再次渲染 这个函数会再次执行
* 2.useState再次执行 得到的新的count值不是0,而是修改后的1,模板会用新值重新渲染
* */
二、useEffect
1.基础使用
import {useState,useEffect} from "react";
// 在修改数据之后,把count值放到页面标题中
// 1.导入 useEffect 函数
// 2.在函数组件中执行 传入回调 并定义副作用
// 3.当我们通过修改状态更新组件时,副作用也会不断执行
function App() {
const [count, setCount] = useState(0)
useEffect(()=>{
// 定义副作用
document.title = count
})
return (
<div className="App">
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
</div>
);
}
export default App;
2.通过依赖项控制执行时机
import {useState,useEffect} from "react";
/*
* 依赖项控制副作用的执行时机
*
* 1.默认状态(无依赖项)
* 组件初始化的时候先执行一次 等到每次数据修改组件更新再次执行
*
* 2.添加一个空数组依赖项
* 组件初始化的时候执行一次
*
* 3.依赖特定项
* 组件初始化的时候执行一次 依赖的特定项发生变化会再次执行
*
* 4.注意事项
* 只要 useEffect 回调函数中用到的数据状态就用该在依赖项数组中声明,否则可能会有bug
* 某种意义上 hook的出现 就是想不用生命周期概念也可以写业务代码
* */
function App() {
const [count, setCount] = useState(0)
const [name,setName] = useState('')
useEffect(()=>{
// 定义副作用
console.log('副作用执行了')
console.log(name)
document.title = count
},[count,name])
return (
<div className="App">
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>增加</button>
<button onClick={() => setName('cp')}>{name}</button>
</div>
);
}
export default App;
三、hooks进阶
1.自定义hook
// src目录下创建useWindowScroll.js文件
import {useState} from "react";
export function useWindowScroll(){
const [Y,setY] = useState(0)
// 在滚动行为发生时 不断获取滚动值 然后交给Y
window.addEventListener('scroll',()=>{
const h = document.documentElement.scrollTop
setY(h)
})
return [Y]
}
// App.js调用
import {useWindowScroll} from "./hooks/useWindowScroll";
function App() {
const [Y] = useWindowScroll()
console.log(Y)
return (
<div style={{height:'12000px'}}>
</div>
)
}
export default App
2.useState回调函数的参数
import {useState} from "react";
function Counter(props) {
const [count, setCount] = useState(() => {
/*
* 这里的目的为了体现初始值经过一定的计算
* 这个计算是比较广义的概念
* 只要无法直接确定 需要通过一定的操作才能获取 就可以理解为计算
* */
return props.count
})
return (
<button onClick={() => setCount(count + 1)}>{count}</button>
)
}
function App() {
return (
<div>
<Counter count={10}></Counter>
</div>
)
}
export default App
3.useEffect清理副作用
import {useEffect, useState} from "react";
function Test() {
useEffect(()=>{
let timer = setInterval(()=>{
console.log('定时器执行了')
},1000)
return ()=>{
//清理操作
clearInterval(timer)
}
},[])
return(
<div>test</div>
)
}
function App() {
const [flag, setFlag] = useState(true)
return (
<div>
{flag ? <Test></Test> : ''}
<button onClick={() => setFlag(!flag)}>切换</button>
</div>
)
}
export default App
4.useEffect发送网络请求
5.hooks中useContext跨组件通信
import React, {createContext, useState, useContext} from 'react'
const Context = createContext()
// 子组件A
function ComA() {
let count = useContext(Context)
return (
<div>
App传给A的数据是:{count}
<ComC></ComC>
</div>
)
}
// 孙子组件C
function ComC() {
let count = useContext(Context)
return (
<div>
App传给C的数据是:{count}
</div>
)
}
// 父组件
function App() {
const [count, setCount] = useState(0)
return (
<Context.Provider value={count}>
<div>
<ComA></ComA>
<button onClick={() => setCount(count + 1)}>增加</button>
</div>
</Context.Provider>
)
}
export default App