最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React Hook

    正文概述 掘金(s叉叉)   2021-02-12   496

    使用Hook的动机

    1. Hook 使你在无需修改组件结构的情况下复用状态逻辑。在Hook之前,我们可以使用render props和高阶组件来添加可复用的状态逻辑。

      render props就是在react组件之间使用一个值为函数的prop共享代码技术,组件接收一个返回React元素的函数,并在组件内部调用这个函数完成渲染逻辑。(这个prop的名字叫render或其他名字),而且也不一定要放到JSX元素的attribute列表中,也可以放在元素标签内部。

      高阶组件(Higher Order Component)是参数为组件,返回值为新组件的函数。HOC将组件包装在容器组件中来组成新的组件,来完成一些可复用的逻辑。

      但这两个方案需要重新组织组件的结构,可能使代码难以理解。使用Hook可以从组件中提取状态逻辑,使这些逻辑可以单独测试且复用,并无需修改组件结构。

    2. 我们维护组件时,随着时间推移,组建的生命周期函数往往变得臃肿,会有很多不相关的状态逻辑。Hook 将组件中相互关联的部分拆分成更小的函数(比如设置订阅或请求数据),而并非强制按照生命周期划分。

    3. Hook 使你在非 class 的情况下可以使用更多的 React 特性。无需理解class

    Hook的特性

    Hook是钩子的意思,就是我们使用函数式组件时,尽量写成纯函数,如果需要React state和生命周期等特性的函数,就使用Hook完成这些原本在class中才能实现的需求。Hook是

    • 完全可选的
    • 100%向后兼容
    • 现在可用
    • 没有计划从React中移除class

    Hook使用规则

    • 只能在函数最外层调用Hook,不要再循环、条件判断或子函数中调用。

    React怎么知道哪个state对应哪个useState,答案是靠Hook执行的顺序,如果我们在条件语句中使用hook,那么很有可能导致前后两次hooks执行顺序发生改变,导致bug产生。如果我们想要有条件地执行一个 effect,可以将判断放到 Hook 的内部。

    • 只能在React的函数式组件中调用,不要在其他JavaScript函数中调用。

    React中几种常见的Hook

    useState

    相当于类组件中的state。

    当我们调用useState时,我们传入一个参数,作为这个state的初始值,它返回一个有两个元素的数组,分别代表当前state的值以及更新这个state的函数,比如[count, setCount] = useState(0),通过数组解构,我们得到两个变量,count是这个state的变量名,我们可以调用setCount更新count这个state。

    使用useState时,应该使用单个state变量还是使用一个对象打包所有state?

    React官方推荐把 state 切分成多个 state 变量,因为每次更新一个state,会用新值整个替换旧值,不像class组件的setState那样合并。因此如果非要用一个对象包含所有state,state的更新要这样实现:

     const [state, setState] = useState({ left: 0, top: 0, width: 100, height: 100 });
     ...
     / 展开 「...state」 以确保我们没有 「丢失」 width 和 height
          setState(state => ({ ...state, left: e.pageX, top: e.pageY }));
    

    useEffect

    useEffect(() => {...}, []);
    

    数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用。我们可以使用useEffect完成在函数式组件中这些功能。

    清除操作:只需在返回值中返回一个函数,那么React会在组件卸载的时候执行清除操作并调用它,比如取消订阅。

    默认情况下,useEffect会在每次渲染后执行,如果要通知React跳过对effect的调用,即不要每次渲染都调用,我们可以传递数组作为第二个参数,比如我们传入[count]作为第二个参数,那么只有当count发生改变时,这个副作用函数才会被执行。

    //相当于componentDidMount和componentWillUnmount
    useEffect(() => {...}, [])
    //会紧紧盯着count,只要count值改变,就会执行
    useEffect(() => {...}, [count])
    //默认情况,相当于componentDidMount和componentDidUpdate
    useEffect(() => {...})
    

    useContext

    在组件之间共享状态的钩子。在React中,如果我们要传递变量,可以使用props属性向下传递给子组件。这种方法很简单,但当我们想把变量传递给子组件的子组件时,就需要使用子组件的props再往下传递,这样就形成了props的深度注入。随着props注入越深,组件更新的频率也越来越高,UI效率也就越来越慢。

    而useContext就是来解决非父子组件的数据共享问题的。

    假设说我们需要全局共享一个变量,username。

    第一步,我们要利用React Context API,在组件外部创建一个context,并传入默认初始值。

    const defaultContextValue = { username: 'sxx' };
    const appContext = React.createContext(defaultContextValue)
    

    然后,为了使App组件和其子组件能共享这个username,我们要用appContext.Provider把整个render函数包裹起来。并且要把defaultContextValue注入到value属性中。

    <appContext.Provider value={defaultContextValue}>
      <App />
    </appContext.Provider>
    

    接下来,我们就可以在他的子孙组件中访问到username这个变量了。

    有两种方法:

    1. 利用appContext.Consumer组件,在组件内部使用花括号,使用箭头函数在其内部共享数据:
    import { appContext } from ...
    ...
      <appContext.Consumer>
      {(value) => {
        {/*在这里可以访问到全局的username啦*/}
        <h1>{value.username}</h1>
      }}
    </appContext.Consumer>
    
    1. 使用React Hook。利用useContext钩子函数,我们不用改变代码的结构,能很方便的在组件中获取数据:
    import { useContext } from 'react';
    const value = useContext(appContext);
    //接着就可以在return中直接使用value了
    

    useContext这个hook极大的减少了模板代码,降低了代码层级,也消灭了多个consumer嵌套的可能性。

    useReducer

    const [state, dispatch] = useReducer(reducer, initialState);
    

    这个钩子接收一个reducer和initialState为参数,返回当前状态和dispatch action的函数,可以在不使用redux的情况下,管理数据状态。

    const myReducer = (state, action) => {
      switch(action.type)  {
        case('countUp'):
          return  {
            ...state,
            count: state.count + 1
          }
        default:
          return  state;
      }
    }
    
    //组件代码
    function App() {
      const [state, dispatch] = useReducer(myReducer, { count:   0 });
      return  (
        <div className="App">
          <button onClick={() => dispatch({ type: 'countUp' })}>
            +1
          </button>
          <p>Count: {state.count}</p>
        </div>
      );
    }
    

    自定义Hook

    自定义 Hook 的命名以use开头,不需要具有特殊的标识。我们可以自由的决定它的参数是什么,以及它应该返回什么(如果需要的话)。

    参考资料:

    1. React Hook官方文档
    2. 阮一峰的网络日志——React Hooks 入门教程

    起源地下载网 » React Hook

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元