React-hooks API介绍

react-hooks HOOKS

  • hooks概念在React Conf 2018被提出来,并将在未来的版本中被引入,hooks遵循函数式编程的理念,主旨是在函数组件中引入类组件中的状态和生命周期,并且这些状态和生命周期函数也可以被抽离,实现复用的同时,减少函数组件的复杂性和易用性。
  • 函数组件 (functional component) 内部能够”钩住“ React 内部的 state 和 life-cycles。
  • 真正功能强大的地方是使我们能够更轻松地复用组件逻辑(custom hooks)
  • 让FunctionalComponent具有ClassComponent的功能

设计Hooks主要是解决ClassComponent的几个问题:

  • 很难复用逻辑(只能用HOC,或者render props),会导致组件树层级很深
  • 会产生巨大的组件(指很多代码必须写在类里面)
  • 类组件很难理解,比如方法需要bind,this指向不明确
 npm install react@16.7.0-alpha.2
 npm install react-dom@16.7.0-alpha.2

 npm install eslint-plugin-react-hooks@next
    // Your ESLint configuration
    {
    "plugins": [
        // ...
        "react-hooks"
    ],
    "rules": {
        // ...
        "react-hooks/rules-of-hooks": "error"
    }
    }

Hooks API Reference

   ** Basic Hooks **
    useState
    useEffect
    useContext

   ** Additional Hooks **
    useReducer
    useCallback
    useMemo
    useRef
    useImperativeMethods
    useMutationEffect
    useLayoutEffect

Rules of Hooks

  • 只能在顶层调用Hooks 。不要在循环,条件或嵌套函数中调用Hook
  • 只能在functional component中使用

State Hook

定义组件状态

  • 避免组件的 state 结构过于臃肿,能够独立处理每个 state
  • 写法非常直观,一眼就可以看出和这个 state 相关的两个变量
    const useStateExample = () => {
        const [count, setCount] = useState(0);
        const [list, setList] = useState([]);
        const [object, setObject] = useState({ name: 'lishishi', age: 28 });
    }

  • State Hooks的定义必须在函数组件的最高一级,不能在嵌套,循环等语句中使用

  • 一个函数组件可以存在多个State Hooks,并且useState返回的是一个数组,数组的每一个元素是没有标识信息的,完全依靠调用useState的顺序来确定哪个状态对应于哪个变量,所以必须保证使用useState在函数组件的最外层

  • 最主要的原因就是你不能确保这些条件语句每次执行的次数是一样的,也就是说如果第一次我们创建了state1 => hook1, state2 => hook2, state3 => hook3这样的对应关系之后,下一次执行因为something条件没达成,导致useState(1)没有执行,那么运行useState(2)的时候,拿到的hook对象是state1的,那么整个逻辑就乱套了,所以这个条件是必须要遵守的!

 const useStateExample = () => {
     if(Math.random() > 1) {
        const [count, setCount] = useState(0);
        const [list, setList] = useState([]);
     }else {
        const [object, setObject] = useState({ name: 'lishishi', age: 28 });
     }
    }

Effect Hook

实现生命周期 (life-cycles)

  • 类似 redux 中的 subscribe,每当 React 因为 state 或是 props 而重新 render 的之后,就会触发 useEffect 里的这个 callback listener(在第一次 render 和每次 update 后触发)
  • 在生命周期内做的操作很多都会产生一些 side-effect(副作用)的操作,比如更新 DOM,fetch 数据,等等。
    useEffect(() => {
        //componentDidMount和componentDidUpdate周期的函数体
        return ()=>{ 
        //componentWillUnmount周期的函数体
        }
    })
    // ---------------------
    useEffect(() => {
        //仅在componentDidMount的时候执行
    },[]);
    // -----------------------
    useEffect(() => {
        //仅在componentDidMount的时候执行
        //只有stateName\props.id的值发生改变
    },[stateName,props.id]);
   
    componentDidUpdate(prevProps, prevState) {
        if (prevState.count !== this.state.count) {
        }
         if (prevProps.id !== this.props.id) {
        }
    }

  • useEffect函数必须位于函数组件的最高一级
useState('Mary')           
useEffect(persistForm)    
useState('Poppins')       
useEffect(updateTitle)

Context Hook

替代了 <Context.Consumer> 使用 render props 的写法,使组件树更加简洁。

Reducer Hook

相当于组件自带的 redux reducer,负责接收 dispatch 分发的 action 并更新 state

配合hooks重新实现react-redux

useReducer + useContext 钩子上进行一层很简单的封装以达到和以往 react-redux \ redux-thunk \ redux-logger 类似的功能

    npm install react-hooks-redux

React.memo() React 16.6.0

  • PureComponent 要依靠 class 才能使用。而 React.memo() 可以和 functional component 一起使用
   const MySnowyComponent = React.memo(function MyComponent(props) {
   // only renders if props have changed!
   });

   // can also be an es6 arrow function
   const OtherSnowy = React.memo(props => {
   return <div>my memoized component</div>;
   });

   // and even shorter with implicit return
   const ImplicitSnowy = React.memo(props => (
   <div>implicit memoized component</div>
   ));

useRef

useCallBack

  • e.g. shouldComponentUpdate ; This is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders
const memoizedCallback = useCallback(
 () => {
   doSomething(a, b);
 },
 [a, b],
);

useMemo

  • useMemo will only recompute the memoized value when one of the inputs has changed
  • useCallback(fn, inputs) is equivalent to useMemo(() => fn, inputs)
 const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useImperativeMethods

  • useImperativeMethods customizes the instance value that is exposed to parent components when using ref
  • useImperativeMethods(ref, createInstance, [inputs])

useMutationEffect useLayoutEffect useEffect 差别

  • useMutationEffect
    It fires synchronously before Layout phase i.e. during the same phase that React performs its DOM mutations. Use it to perform blocking custom DOM mutations without taking any DOM measurement/reading layout.

  • useLayoutEffect
    It fires synchronously after all DOM mutations but before Paint phase. Use this to read layout(styles or layout information) from the DOM and then perform blocking custom DOM mutations based on layout.

  • useEffect
    It runs after the render is committed to the screen i.e. after Layout and Paint phase. Use this whenever possible to avoid blocking visual updates

注意

  • 目前react-hot-loader不能和hooks一起使用

Mixin => HOC => Render Prop => hooks

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 8,523评论 1 33
  • 本文将开始详细分析如何搭建一个React应用架构。 一. 前言 现在已经有很多脚手架工具,如create-reac...
    字节跳动技术团队阅读 4,399评论 1 23
  • React.js 小书学习 之 【使用 JSX 描述 UI 信息】 从 JSX 到页面 过程图解:JSX 到页面过...
    zdlucky阅读 1,296评论 0 20
  • ——任何时候,都要攒足人品,相信爱情。 单身、大龄、博士,还会遇到理想中的爱情吗?会的。只要做好准备,攒足人品,男...
    Annie_66d0阅读 426评论 0 0
  • 《我的诗词》目录 百万家庭夜不眠,通宵达亘网波点。 一纸捷报雪霜剪,展翅飞翔新梦燃。
    青梅梦语阅读 825评论 8 28