Hooks 是一项新功能提案,可以在不编写类的情况下使用 state(状态) 和其他 React 功能。
useState
import React, { useState } from 'react';
function Test() {
const [count, setCount] = useState(0)
const [username, setUsername] = useState('布丁')
const [age] = useState(17)
return (
<div>
<p>姓名:{username}</p>
<p>年龄:{age}</p>
<p>数字:{count}</p>
<button onClick={() => {
setCount(count + 1)
}}>点击数字+1</button>
<button onClick={() => {
setCount(count - 1)
}}>点击数字-1</button>
</div>
)
}
export default Test;
语法:const [state, setState] = useState(initialState);
- 传入唯一的参数: initialState,可以是数字,字符串等,也可以是对象或者数组。
- 返回的是包含两个元素的数组:第一个元素,state 变量,setState 修改 state值的方法。
与在类中使用 setState 的异同点:
- 相同点:也是异步的,例如在 onClick 事件中,调用两次 setState,数据只改变一次。
- 不同点:类中的 setState 是合并,而函数组件中的 setState 是替换
useEffect
useEffect增加了从函数式组件执行副作用的功能。它与 React 类中的 componentDidMount,componentDidUpdate,和 componentWillUnmount 有相同的功能,但是统一为单个 API。(相当于这三个生命周期的组合)
import React, { useState, useEffect } from 'react';
function Test() {
const [count, setCount] = useState(0)
const [username, setUsername] = useState('布丁')
const [age] = useState(17)
useEffect(() => {
console.log(count,age)
})
return (
<div>
<p>姓名:{username}</p>
<p>年龄:{age}</p>
<p>数字:{count}</p>
<button onClick={() => {
setCount(count + 1)
}}>点击数字+1</button>
<button onClick={() => {
setCount(count - 1)
}}>点击数字-1</button>
</div>
)
}
export default Test;
语法:useEffect(didUpdate);
有两个参数:
第一个参数是一个函数,是在第一次渲染以及之后更新渲染之后会进行的副作用。
这个函数可能会有返回值,倘若有返回值,返回值也必须是一个函数,会在组件被销毁时执行。
第二个参数为可选参数:
- 当什么都不传的时候,则每次更新都会执行。(相当于componentDidMount,componentDidUpdate)。
- 当传的参数是一个空数组[ ]时,则useEffect只执行一次。告诉 React 你的 effect 不依赖于组件中的任何值,仅在组件挂载和卸载时执行,从不在更新时运行。
useEffect(() => {
console.log(count)
}, [])
- 当传的参数是state中的数据的数组时[age,count],则每次数组当中的数据发生变化时useEffect才执行。
useEffect(() => {
console.log(count)
}, [count])
useReducer
语法:const [state, dispatch] = useReducer(reducer, initialArg, init);
useState 的替代方案。 接受类型为 (state, action) => newState 的reducer,并返回与 dispatch 方法配对的当前状态。
import React, { useState, useEffect, useReducer } from 'react';
const initState = { count: 0 }
function reducer(state, action) {
switch (action.type) {
case 'add':
return { count: state.count + 1 };
case 'minus':
return { count: state.count - 1 };
case 'reset':
return initState;
default:
return state
}
}
function Test() {
// const [count, setCount] = useState(0)
// const [username, setUsername] = useState('布丁')
// const [age] = useState(17)
const [state, dispatch] = useReducer(reducer, initState)
useEffect(() => {
console.log(state.count)
}, [state.count])
return (
<div>
{/* <p>姓名:{username}</p>
<p>年龄:{age}</p> */}
<p>数字:{state.count}</p>
<button onClick={() => {
dispatch({
type: 'add'
})
}}>点击数字+1</button>
<button onClick={() => {
dispatch({
type: 'minus'
})
}}>点击数字-1</button>
<button onClick={() => {
dispatch({
type: 'reset'
})
}}>重置</button>
</div>
)
}
export default Test;
useReducer 接受可选的第三个参数 initialAction 。如果提供,则在初始渲染期间应用初始操作。这对于计算包含通过 props(属性) 传递的值的初始 state(状态) 非常有用
import React, { useState, useEffect, useReducer } from 'react';
//const initState = { count: 0 }
function init(initialCount) {
return { count: initialCount };
}
function reducer(state, action) {
switch (action.type) {
case 'add':
return { count: state.count + 1 };
case 'minus':
return { count: state.count - 1 };
case 'reset':
return init(action.payload);
default:
return state
}
}
function Test({initialCount = 0}) {
// const [count, setCount] = useState(0)
// const [username, setUsername] = useState('布丁')
// const [age] = useState(17)
const [state, dispatch] = useReducer(reducer, initialCount,init)
useEffect(() => {
console.log(state.count)
}, [state.count])
return (
<div>
{/* <p>姓名:{username}</p>
<p>年龄:{age}</p> */}
<p>数字:{state.count}</p>
<button onClick={() => {
dispatch({
type: 'add'
})
}}>点击数字+1</button>
<button onClick={() => {
dispatch({
type: 'minus'
})
}}>点击数字-1</button>
<button onClick={() => {
dispatch({
type: 'reset',
payload: initialCount
})
}}>重置</button>
</div>
)
}
export default Test;