[React03|青训营笔记]

74 阅读3分钟

第三章 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>
            </>
        );
    }