第三章 React Hooks
只修改变量如果没有更新视图仍然不能在界面上有所体现
hook只能用在组件函数的最顶层
函数式组件
创建函数式组件时 首字母必须大写 render方法的第一个参数写函数的同名标签,此处标签必须闭合,如果不习惯写自闭合可以写两个。
过程:react解析组件标签,找到相应组件,发现组件是用函数定义的,随后调用该函数,将返回的虚拟dom转为真实dom,随后呈现在界面上
3.1 useState
函数组件没有state,无法通过setState来更新视图。
在react包中导入useState钩子,然后在组件函数的顶部调用useState()
3.11读取状态
被调用时,返回一个数组,第一项是一个状态值
const stateArray = useState(false);
stateArray[0]; // => 状态值
一般通过数组解构提取到变量上。
第二项是一个更新状态的函数,用来更新第一项。
const [state, setState] = useState(initialState);
setState(newState);
调用更新器后将重新渲染,使新状态变为当前状态。
3.12 一些注意事项
- 仅能在顶层调用Hook(不能在循环条件嵌套函数中调用),多个useState()调用中,渲染之间的调用顺序必须相同
- 仅在函数组件或自定义钩子内部调用useState()
- 在单个组件中可以用多个状态,调用多次useState()
3.13 复杂状态管理&useReducer()
官方提供的两种状态管理的hook:useState和useReducer.
没有useReducer也能完成正常开发,但使用它可以让代码具有更好的可读性、可维护性、可预测性
什么是reducer
是一个函数(state,action)=>newState
接受当前应用的state和动作action,计算并返回最新的state
例:计算器reducer
// 计算器reducer,根据state(当前状态)和action(触发的动作加、减)参数,计算返回newState
function countReducer(state, action) {
switch(action.type) {
case 'add':
return state + 1;
case 'sub':
return state - 1;
default:
return state;
}
}
reducer的幂等性
本质上是一个纯函数,相同的输入无论执行多少遍都会返回相同的输出(newState)
state和newState的理解
当state是一个复杂的js对象时:
// 返回一个 newState (newObject)
function countReducer(state, action) {
switch(action.type) {
case 'add':
return { ...state, count: state.count + 1; }
case 'sub':
return { ...state, count: state.count - 1; }
default:
return count;
}
}
1.处理的state对象必须是immutable,永远不要直接修改参数中的state对象的值而是返回一个新的state object;
2.因为reducer要求每次返回一个新的对象,可以用ES6中的解构赋值方式去创建一个新对象,并复写需要改变的state属性。
action理解
action:用来表示触发的行为
1.用type来表示具体的行为类型
2.用payload携带数据
例
const action = {
type: 'addBook',
payload: {
book: {
bookId,
bookName,
author,
}
}
}
reducer是一个利用action提供的信息将state从A转换到B的一个纯函数:
-
语法: (state, action) => newState
-
Immutable:每次都返回一个newState, 永远不要直接修改state对象
-
Action:一个常规的Action对象通常有type和payload(可选)组成
- type: 本次操作的类型,也是 reducer 条件判断的依据
- payload: 提供操作附带的数据信息
Wen Reducer?
当state是一个数组或对象,变化复杂,一个操作需要修改很多state的时候
对于复杂的状态管理,可以使用useReducer()这一hook,将reducer提取到一个单独的模块中,并在其他组件中重用它。
const [state, dispatch] = useReducer(reducer, initState);
//官方useReducer Demo
//第一个参数 应用的初始化
const initialState = {count: 0};
// 第二个参数:state的reducer处理函数
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
// 返回值:最新的state和dispatch函数
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
// useReducer会根据dispatch的action,返回最终的state,并触发rerender
Count: {state.count}
// dispatch 用来接收一个 action参数「reducer中的action」,用来触发reducer函数,更新最新的状态
<button onClick={() => dispatch({type:'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}