本教程是React Hooks系统教程中的一部分。
React 函数组件本身不包含状态和生命周期,因此需要使用一些 Hooks (勾子)函数来实现状态保持、状态共享和传递。
useState
可以通过 useState 为函数组件添加内部状态。组件会侦听 state 的状态变化并重新 render 渲染组件。下面我们使用 useState 创建了一个计数器,文件名为 ExampleState.js
此示例实现单击按钮,增加计数。
import React, { useState } from "react";
export function ExampleState() {
const [count, setCount] = useState(0);
return (
<div>
<hr/>
<h1>useState: {count}</h1>
<button onClick={()=>{ setCount(count+1) }}>Click me</button>
</div>
)
}
const [count, setCount] = useState(0); 代表 count 初始值为 0, 通过 setCount 改变 count 的值。
类似于通过扩展React.Component
或创建的Class组件中的setState,React.PureComponent
使用useState
钩子提供的更新程序的状态更新也是异步的,不会立即反映和更新,但会触发重新渲染
setMovies(result);
console.log(movies) // movies here will not be updated
如果要对状态更新执行操作,则需要使用useEffect钩子,就像componentDidUpdate
在类组件中使用一样,因为useState返回的setter没有回调模式
useEffect(() => {
// action on update of movies
}, [movies]);
就更新状态的语法而言,setMovies(result)
将状态中的先前movies
值替换为异步请求中可用的值
但是,如果要将响应与先前存在的值合并,则必须使用状态更新的回调语法以及正确使用的扩展语法,例如
setMovies(prevMovies => ([...prevMovies, ...result]));
2020-04-25
useEffect
useEffect 可以用来侦听状态变化,并执行相应逻辑。!!!!!!适用于父组件传递过来的参数,无法给子组件useState设置初始值时使用。因为不确定上传父组件什么时候将值传递过来,所以使用useEffect进行对父组件值的监听,改变的时候再用useState进行赋值
const [userGroupList, setUserGroupList] = useState([]);//获取前台给的分组信息
useEffect(() => {
let a = props.userGroupList;//当userGroupList在父类中有值的时候,进行setState方法
console.log('props.userGroupList===',props.userGroupList);
console.log('a===',a);
setUserGroupList(a);
}, [props.userGroupList]);//当 useEffect 带参数时,参数的变化才会触发 useEffect 的执行。此时可使用 useState。
无参数
当 useEffect 无参数使用时,会侦听当前组件所有状态的变化,因此不带参数的 useEffect 函数中不能使用useState方法来改变state,否则会触发无限循环:
下面的例子,当点击 Click me 按钮时,都会执行 useEffect 中的函数,改变 effect 显示值。
import React, { useState, useEffect } from "react";
let effect = 0;
export function ExampleEffect() {
const [count, setCount] = useState(0);
useEffect(()=>{
document.getElementById('effect').innerText = ++effect;
})
return (
<div>
<hr/>
<h1>useEffect 无参数 effect:<b id="effect"></b> count: {count}</h1>
<button onClick={()=>{ setCount(count+1) }}>Click me</button>
</div>
)
}
并且effect的值始终比count多1,因为useEffect第一次渲染时也会执行,效果如下图所示:
带参数
当 useEffect 带参数时,参数的变化才会触发 useEffect 的执行。此时可使用 useState。
import React, { useState, useEffect } from "react";
export function ExampleEffectArgs() {
const [count, setCount] = useState(0);
const [effect, setEffect] = useState(0);
useEffect(()=>{
setEffect(effect+1);
}, [count])
return (
<div>
<hr/>
<h1>useEffect 带参数 effect:{effect} count: {count}</h1>
<button onClick={()=>{ setCount(count+1) }}>Click me</button>
</div>
)
}
这段代码的效果与上面的例子相同。
空参数
当 useEffect 传入空参数 [] 时,只有当第一次渲染(mount) 和不渲染(unmount)时执行。
完整示例: