React Hooks简单业务场景实战(非源码解读)

栏目: IOS · Android · 发布时间: 6年前

内容简介:React Hooks 是React 16.7.0-alpha 版本推出的新特性。从 16.8.0 开始,React更稳定的支持了这一新特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。注意:React 16.8.0 是第一个支持 Hook 的版本。升级时,请注意更新所有的 package,包括 React DOM。React Native 将在下一个稳定版本中支持 Hook。

React Hooks 是React 16.7.0-alpha 版本推出的新特性。从 16.8.0 开始,React更稳定的支持了这一新特性。

它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

注意:React 16.8.0 是第一个支持 Hook 的版本。升级时,请注意更新所有的 package,包括 React DOM。React Native 将在下一个稳定版本中支持 Hook。

如果说promise是JavaScript异步的终极解决方案,那么React Hooks从某种意义上来说,也是react状态管理的终极解决方案。

为什么用 React Hooks?与其他状态管理方案有什么区别?

在react hooks,react态管理方案主要有如下2种:

这两种状态解决方案其实已经很不错,可以满足绝大多数状态共享的业务场景。 当然,像FB这样优秀的团队优秀的人总喜欢钻研,不断优化。认为这两种状态解决方案嵌套太多,很多业务逻辑可以抽象出来。不仅仅是共享状态就完事了,还得共享出处理逻辑。 为了减少不必要的组件嵌套写法,实现更扁平、颗粒化的状态 + 逻辑的复用,于是便推出了 React Hooks

关于react hooks,具体可以多看看React Hooks官方文档,理解会更深。

业务实战1:实现一个简单的显示隐藏弹出框

1、基于 render-props实现:

// 将父组建的 on状态 和toggle 事件,共享给嵌套下的子组件
function App() {
 return (
   <Toggle initial={false}>
     {({ on, toggle }) => (
       <Button type="primary" onClick={toggle}> Open Modal </Button>
       <Modal visible={on} onOk={toggle} onCancel={toggle} />
     )}
   </Toggle>
 )
}
复制代码

2、用react hooks实现

import React, { useState } from 'react';

function Example() {
  // 声明一个新的叫做 “visible” 的 state 变量
  const [visible, setVisible] = useState(false);

  return (
    <div>
      <Modal onClick={() => setVisible(!visible)}>
        Click me
      </Modal>
    </div>
  );
}
复制代码

业务实战2: 接收传入props后立马更新自有的State状态(received passed props and updated)

function Avatar(props) {
 const [user, setUser] = React.useState({...props.user}); // 这里仅仅是给了一个初始值,仅第一次渲染的时候生效,后续都不会再更新了。

 // 用useEffect,第二个参数传入一个数组字段props.user,
 // 表示每次只要传入的props.user有变化,那么就触发setUser这个操作更新状态。
 React.useEffect(() => {
     setUser(props.user);
 }, [props.user])

 return user.avatar ? 
        (<img src={user.avatar}/>)
       : (<p>Loading...</p>);
}
复制代码

由上述例子可以看到,我们用到了useEffect这个hooks。

Effect Hook 可以让你在函数组件中执行副作用操作

什么叫副作用呢? 数据获取,设置订阅以及手动更改 React 组件中的 DOM 都属于副作用。

如果实在理解不了副作用,你可以理解为,在我们在写传统的react class组件里面的生命周期钩子函数componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合中处理的相关逻辑,就是副作用。

也就是说,任何你想在页面首次加载完(componentDidMount),后续每次更新完(componentDidUpdate),亦或者是组件卸载前(componentWillUnmount),这三个勾子中加入你自己的逻辑处理,就得用到useEffect

业务实战3:显示后,倒计时自动隐藏(与setInterval结合)

业务场景具体如下:实现一个倒计时30秒,每秒钟减1,然后倒计时完毕这个组件自动隐藏。

function App() {
  const [count, setCount] = useState(30);
  useEffect(() => {
    setInterval(() => {
      setCount(count - 1);
    }, 1000);
  });
  return <div className="App">{count}</div>;
}
复制代码

看看上述的写法,自己运行一下就只知道了,肯定是大错特错的。 最基本的,setInterval这个删除定时器都没有做相关处理。 其次,每次都会生成不同都setInterval实例。那么如何加以控制呢?

来看看正确都写法,这里要用到useRef这种类型都hooks了。

function App(props){
    const [visible,setVisible] = useState(false);// 初始化值为false,隐藏
    const [count,setCount] = useState(0); // 倒计时字段,初始值为0
    // 明确定时器要做什么:我们这里是每秒 -1,小于等于0的时候就自动给隐藏
    // 同时,本此的跟新跟下次的渲染更新要共享状态,记住上次更新这个count减到哪里了
    // 基于上述问题,我们可以使用如下方案:
    // 声明一个useRef对象,初始化为null
    const intervalCb = useRef(null); 
    useEffect(()=>{
      // useRef 对象有一个current属性,可以给它赋值为一个函数
      intervalCb.current = () => { 
      if(count  <= 0){
        setVisible(false);
      }else{
        setCount(count - 1);
      }    
    };   
    })
    
    // 在componentDidMount中设置一个定时器
    useEffect(()=>{
        function itvFn(){
            // 在此前,定时器的回调函数已经声明,这里可以直接调用
            intervalCb.current(); 
        }
        const itvId = window.setInterval(itvFn,1000);
        // return 一个回调函数,表示清除处理
        return () => window.clearInterval(itvId);
    },[]) // 传入要监听的对象,空数组表示只监听一次,相当于didMounted
}

return (<div className={visible}>
        {count}
    </div>)
}
复制代码

关于useRef 更多的请看useRef官方文档

业务实战4: 自定义hooks

基于上述setInterval的业务功能实现,我们简单的来写一个自定义的hooks

export default function useInterval(callback) {
 const savedCallback = useRef();

 useEffect(() => {
   savedCallback.current = callback;
 });

 useEffect(() => {
   function tick() {
     savedCallback.current();
   }

   let id = setInterval(tick, 1000);
   return () => clearInterval(id);
 }, []);
}
复制代码

然后在你需要用到的地方引入:

import useInterval from 'xx/self_hooks';

function App(){
   useInterval(()=>{
       // ... 跟useEffect写法类似,目前只支持传入一个function类型的参数,如果要接收多个参数,那么在自定义hooks那里去自行处理一下。
   })
}
复制代码

关于自定义hooks,更多请查看自定义hooks

暂结

关于react hooks 简单的使用,此篇就暂时写到这里,当然,复杂一点的,可以使用useReducer、useContext和useEffect代替Redux方案。后续我们应该单独来研究这块。 回顾一下,如何才能说我们会用react hooks 呢?

  • 第一、明白概念,干什么用的,解决哪些痛点?
  • 第二、useEffect传入几个参数?分表表示声明?useRef作用是什么?这些可以解决我们基本的业务需求。
  • 第三、useReducer、useContext 怎么替换 redux?
  • 读源码,搞清楚为什么useEffect不能卸载if嵌套中等之类的问题?

今天先把问题抛出,后续按照这个,循序渐进的学习掌握react hooks。


以上所述就是小编给大家介绍的《React Hooks简单业务场景实战(非源码解读)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Realm of Racket

Realm of Racket

Matthias Felleisen、Conrad Barski M.D.、David Van Horn、Eight Students Northeastern University of / No Starch Press / 2013-6-25 / USD 39.95

Racket is the noble descendant of Lisp, a programming language renowned for its elegance and power. But while Racket retains the functional goodness of Lisp that makes programming purists drool, it wa......一起来看看 《Realm of Racket》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具