在react18中,任何情况下 setState更新数据都是异步的!18以下版本,在定时器和原生事件中是同步的。
this.setState({key:新val},()=>{ 获取最新值 }) 合并更新
this.setState(oldState=>(return {key:新val}),()=>{ 获取最新值 }) 每一次都会执行
hooks:是 React v16.8 中的新增功能
- 为函数组件提供状态、生命周期等原本 class 组件中提供的 React 功能
- 可以理解为通过 Hooks 为函数组件钩入 class 组件的特性
- 注意:Hooks 只能在函数组件中使用
useState:为函数组件提供状态
使用:useState(初始值) 返回 一个数组,第一个元素是定义的状态,第二个元素是修改状态的方法
使用步骤:
- 导入 useState hook
- 调用 useState 函数,并传入状态的初始值
- 从 useState 函数的返回值中,拿到状态和修改状态的函数
- 在 JSX 中展示状态
- 在按钮的点击事件中调用修改状态的函数,来更新状态
import React, { useState } from 'react'
const App = () => {
const [msg,setMsg] = useState('你好hooks')
return (
<div>
<p>msg的数据是:{msg}</p>
<p>
<button onClick={()=>setMsg('我是修改的内容')}>修改msg</button>
</p>
</div>
)
}
export default App
------------------------------------------------------------------------
import React, { useState } from 'react'
const App = () => {
const [person, setPerson] = useState({name:'zs',age:20})
const [list, setList] = useState(['zs','ls','ww'])
const changeAge =()=>{
setPerson({...person,age:person.age+1})
}
const changeList1 = ()=>{
list.splice(0,1,'sq')
setList([...list])
}
const changeList2 = ()=>{
setList([...list,'666'])
}
return (
<div>App
<p>姓名是:{person.name},年龄是:{person.age}</p>
<p>
<button onClick={changeAge}>年龄+1</button>
</p>
<hr/>
<p>list的数据是:{JSON.stringify(list)}</p>
<p>
<button onClick={changeList1}>改变第一个元素</button>
<button onClick={changeList2}>末尾添加</button>
</p>
</div>
)
}
export default App
const [ 变量,修改方法 ] = useState(初始值)
- 修改数据方式1: 修改方法(新值) ===>合并策略
- 修改数据方式2: 修改方法(老值=>新值) ===> 每个都执行
const [count, setCount] = useState(10)
const changeCount =()=>{
// setCount(count+1)
// setCount(count+2)
// setCount(count+3)
setCount(oldCount=>oldCount+1)
setCount(oldCount=>oldCount+2)
setCount(oldCount=>oldCount+3)
}
useEffect:副作用
- 对于 react 组件来说,除了渲染 UI 之外的其他操作,都可以称之为副作用
- 常见的副作用(side effect):数据(Ajax)请求、手动修改 DOM、localStorage、console.log 操作
useEffect副作用
==>副作用:渲染之外的操作都称之为副作用
- 方式1:useEffect(()=>{ 逻辑代码 }) componentDidMount 和 componentDidUpdate
- 方式2:useEffect(()=>{ 逻辑代码 },[ 变量 ]) 类似watch的作用(类似监听器的作用,当变量发生变化的时候,才会执行逻辑代码)
- 方式3:useEffect(()=>{ 逻辑代码 },[ ]) componentDidMount)(挂载完成之后)
- 方式4:useEffect(()=>{ 逻辑代码 return=>{ 销毁的时候要做的事 } },[ ]) 类似componentWillUnmount
方式4是useEffect清除副作用,返回一个清理函数,执行事件解绑等清理操作。
import React, { useEffect } from 'react'
const Child =()=>{
let timer = null
useEffect(()=>{
timer=setInterval(()=>{
console.log('react');
},1000)
return ()=>{
clearInterval(timer)
}
},[])
return (
<div>child</div>
)
}
export default Child
----------------------------------------------
import React, { useState } from 'react'
import Child from './Child'
const App = () => {
const [show, setshow] = useState(false)
return (
<div>
{show?<Child></Child> : '没有了'}
<button onClick={()=>setshow(!show)}>切换</button>
</div>
)
}
export default App
import React, { useEffect, useState } from 'react'
const App = () => {
const [count, setCount] = useState(20)
useEffect(() => {
console.log('count的数据是'+count);
document.title = `当前已点击 ${count} 次`;
},[count])
useEffect(()=>{
console.log('发送ajax请求');
},[])
useEffect(()=>{
window.addEventListener('resize',()=>{
console.log('尺寸调整了');
})
},[])
const [loading, setloading] = useState(false)
return (
<div>
<p>count的数据是:{count}</p>
<p>
<button onClick={()=>setCount(count+1)}>count+1</button>
</p>
<hr/>
<div>
{loading?<div>加载中</div>:<div>加载完成</div>}
</div>
<button onClick={()=>setloading(!loading)}>切换</button>
</div>
)
}
export default App