react-hooks

Hook的使用规则

只能在函数的最外层去使用,不要在循环中或者子函数中去调用

只能在react的函数组件中去调用,也可以在自定义的hooks中去调用

useState

useState 其实就是个状态逻辑函数,通过数组的解构方式去获取一个值和对应这个值的操作方法

const [xxx,setXxx] = useState('defaultValue')

并且第二个参数是个赋值函数,也可以去调用自定义函数去运行 

相对于class组件中的优点

  • 在状态管理中颗粒度更细
  • 代码相对与class而言也比较清晰 
  • 容易做状态分类
  • 采用平铺的写法

Props.children也可以采用这样的写法

const Parent = props => {

  const [count, setCount] = useState(0);

  return props.children(count, setCount);

};


const TestPage = () => {

  return (

      <Parent>

        {(count, setCount) => {

          return (

            <button onClick={() => {

                setCount(count + 1);

              }}

            >

              clickNum {count}

            </button>

          );

        }}

      </Parent>

  );

};

useEffect

useEffect 就是指明react在对dom进行更改后,需要运行的函数

因为hooks属于无状态的组件,所以也没有class组件生命周期一说

  • 也可用于做优化页面性能
  • 可以使用useEffect去模拟class的生命周期(简单理解来说)

useEffect第二个参数是所依赖的值(props传入的值),数组形式,可以写多个

它会判断props的传值和他的上次进行一次浅比较,如果发现有变化,才回去执行,无变化,则不执行。

useEffect(()=>{ 
 console.log('do something') 
},['depValue'])

模拟类的didMount 

useEffect(()=>{ console.log('do something') },[])

如需清除副作用,可以直接在回调函数中return出一个处理函数

useEffect(()=>{ 
 console.log('do something') 
  return ()=>{
   console.log('clear effect')
 }
})

副作用:指当前hooks在函数作用域以外所处理的事情

UseContext

无需使用组件嵌套的形式,就可以订阅react的上下文

换而言之 传统组建通信,数据流基本都是props向下派发的,但是context 可以直接无视子组件嵌套层级与底层的子组件直接通信  

典型例子就是redux 就是使用react提供的context的技术做的数据管理

使用UseContext的例子

const ctx = React.createContext();
const myContext = useContext(ctx);

const SubComponent = ()=>{
   const {count,setCount} = useContext(myContext);

   return <button
             onClick={()=>{
              setCount(coun+1)
               }}
              >
          {count}
        </button>
}

const App = ()=>{
  const [count,setCount] = useState(0);
  return <ctx.provider
            value={{
              count,
               setCount,
            }}
            >
       <div>
        <div>
          <subComponent />
        </div>
      </div>
     </ctx.provider>
}

useReducer

useReducer  自定义state 和redux类似

useReducer 返回一个state和dispatch方法,后者用于修改前者的值

useReducer 参数描述

 第一个参数 是处理函数 用于disptach后区分操作类型

 第二个参数 用于当前state的默认值   init初始值   (initialArg)

 第三个参数 作用与当前的state,相当于init (initialArg),是 一个函数需要将 init 函数作为 useReducer 的第三个参数传入,这样初始 state 将被设置为 init(initialArg)。

示例

const reducer = (state, action) => {
  switch (action.type) {
    case "acc": return { ...state, count: state.count + 1 };
    case "ded": return { ...state, count: state.count - 1 };
    case "save": save(123);
    default: return state;
  }

};

const save = state => state;

const TestPage = () => {

  const [state, dispatch] = useReducer(reducer,

    {

      count: 1,

      data: 

    },

    save

    //这个save方法可以单独抽离出来 进行逻辑判断 搭配useReducer的第三个参数使用,

  );

  return (

      <button onClick={() => {

          dispatch({

            type: "acc"

          });

        }}

      >
        {state.count}

      </button>
  );

};

useMemo

避免在每次渲染时都进行高开销的计算

缓存计算结果的值(写法类型useEffect)

如果props的依赖值没有发生变化  函数不会执行, 缓存上次计算的状态

传入 useMemo 的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于useEffect 的适用范畴,而不是 useMemo。

如果没有提供依赖项数组,useMemo 在每次渲染时都会计算新的值。

示例

useMemo(()=>{

 console.log('do something')
 //复杂的逻辑计算

},[value])

useCallBack

useCallBack 缓存函数

第一个参数是回调函数

第二个是更新依赖项, 依赖项为空则直接缓存 ,反之依赖项发生变化 执行回调

传入子组件的的函数会被重新声明  使用useCallBack进行缓存

useMemo和useCallback的区别 

useMemo 计算结果是 return 回来的值, 主要用于 缓存计算结果的值 ,应用场景如: 需要 计算的状态

useCallback 计算结果是 函数, 主要用于 缓存函数,应用场景如: 需要缓存的函数,因为函数式组件每次任何一个 state 的变化 整个组件 都会被重新刷新,一些函数是没有必要被重新刷新的,此时就应该缓存起来,提高性能,和减少资源浪费。

useRef   

useRef会返回一个可变的ref对象  直接插入使用   ref.current值为当前dom

useImperativeHandle

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值

function FancyInput(props, ref) {

  const inputRef = useRef();

  useImperativeHandle(ref, () => ({

    focus: () => {

      inputRef.current.focus();

    }

  }));

  return <input ref={inputRef} ... />;

}

FancyInput = forwardRef(FancyInput);

  

React.forwardRef 会创建一个React组件,这个组件能够将其接受的 ref 属性转发到其组件树下的另一个组件中

useLayoutEffect

useLayoutEffect的执行时机是浏览器把内容真正渲染到界面之前和 componentDidMount 等价。相比于useEffect不会有闪烁的问题;

为什么会有闪烁的问题·

useEffect是dom渲染完毕后去异步执行的,如果在这个过程中在触发重新渲染,就会导致原本渲染的内容再被渲染一次,从而出现闪烁的现场。而useLayoutEffect相当于渲染之前同步进行的,等它这次操作执行完毕后在进行渲染,所以不会闪烁。

useDebugValue

useDebugValue 打印日志到react-dev-tools 第二个参数为可选为一个格式化参数,接受debug的值作为参数,并且返回一个格式化的值

上一篇:React核心 -- React-Hooks


下一篇:hooks中几种钩子的基本使用方法学习总结