温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

React如何从Class方式转Hooks

发布时间:2021-09-30 09:13:12 来源:亿速云 阅读:189 作者:小新 栏目:开发技术

这篇文章主要为大家展示了“React如何从Class方式转Hooks”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“React如何从Class方式转Hooks”这篇文章吧。

    Why Hooks ?

    Hooks很大的一个亮点是可以进行业务逻辑的重用。这一点在hooks中体现的尤为明显。比如,往常的class中如果要去监听窗口大小的变化的时候,就得在组件中在挂载后去添加监听事件,但是如果当另外一个地方需要用到这种监听窗口大小功能的话,这种逻辑代码并不可以复用,只能在那个组件中重新写一遍。但是在hooks中,我们可以将这部分监听的逻辑代码进行hooks方式封装,完全可以做到逻辑上的复用。

    For Class
    • 使用Class作为React的载体的时候:

    • 组件之间不会相互继承,没有利用到class的继承的特性UI是状态驱动的,所有的方法都是内部调用或者作为生命周期的方法内部自动调用。没有使用到类的实例方法可以调用的特性

    For Function

    React中的一个核心就是要实现从State数据到View试图层面的一个绑定。使用函数,其实更好的去解决State到View的一个映射问题。但是,用函数作为React的载体就会出现两个问题,函数中状态的保存以及生命周期的方法

    • Hooks怎样去解决上面两个问题:把一个外部的数据绑定到函数的执行。当数据变化时,让函数能够自动重新执行。这样的话,任何会影响 UI 展现的外部数据,都可以通过这个机制绑定到 React 的函数组件。

    • Hooks钩子的理解:把某个目标结果钩到某个可能会变化的数据源或者事件源上,那么当被钩到的数据或事件发生变化时,产生这个目标结果的代码会重新执行,产生更新后的结果

    React如何从Class方式转Hooks

    图解:一个执行过程(Execution),例如是函数组件本身,可以绑定在(钩在)传统意义的 State,或者 URL,甚至可以是窗口的大小。这样当 State、URL、窗口大小发生变化时,都会重新执行某个函数,产生更新后的结果。

    Class & Hooks 对比
    • 比起 Class 组件,函数组件是更适合去表达 React 组件的执行的,因为它更符合 State => View 这样的一个逻辑关系。但是因为缺少状态、生命周期等机制,让它一直功能受限。Hooks解决了函数组件作为React载体的状态生命周期等受限问题,让其功能充分发挥出来

    • Hooks 中被钩的对象,可以是某个独立的数据源,也可以是另一个 Hook 执行的结果,这就带来了 Hooks 的最大好处:逻辑的复用

    • 简化了逻辑复用

      • Class方式中:使用高阶组件的设计模式进行逻辑复用。比如:我们要去复用一个窗口resize的功能,我们需要去定义一个没有UI的外层组件,去写相关resize的逻辑定义,然后将数据结果用属性的方式传给子组件。组件要复用这个逻辑的话,必须外层用这个组件包裹并返回。针对整个而言,**为了传递一个外部的状态,我们不得不定义一个没有 UI 的外层组件,而这个组件只是为了封装一段可重用的逻辑。**频繁使用,每一个高阶组件的使用都会多一层节点,会给调试等带来很大的负担。

    //Class中高阶组件实现resize方法复用
    //1、高阶组件的声明
    const withWindowSize = Component => {
      // 产生一个高阶组件 WrappedComponent,只包含监听窗口大小的逻辑
      class WrappedComponent extends React.PureComponent {
        constructor(props) {
          super(props);
          this.state = {
            size: this.getSize()
          };
        }
        componentDidMount() {
          window.addEventListener("resize", this.handleResize); 
        }
        componentWillUnmount() {
          window.removeEventListener("resize", this.handleResize);
        }
        getSize() {
          return window.innerWidth > 1000 ? "large" :"small";
        }
        handleResize = ()=> {
          const currentSize = this.getSize();
          this.setState({
            size: this.getSize()
          });
        }
        render() {
          // 将窗口大小传递给真正的业务逻辑组件
          return <Component size={this.state.size} />;
        }
      }
      return WrappedComponent;
    };
    //2、组件MyComponent使用高阶组件中的resize功能
    class MyComponent extends React.Component{
      render() {
        const { size } = this.props;
        if (size === "small") return <SmallComponent />;
        else return <LargeComponent />;
      }
    }
    // 使用 withWindowSize 产生高阶组件,用于产生 size 属性传递给真正的业务组件
    export default withWindowSize(MyComponent);
    • Hooks方式中:实现resize的话,窗口大小只是外部的一个数据状态。我们使用hooks方式对其封装,只是将其变成了一个可以绑定的数据源,当窗口大小发生变化的时候,这个组件也会重新渲染代码会更加简洁直观,并且不会产生额外的组件节点。

    //Hooks中使用hooks方法进行resize逻辑复用
    //定义useWindowSize这个hook
    const getSize = () => {
      return window.innerWidth > 1000 ? "large" : "small";
    }
    const useWindowSize = () => {
      const [size, setSize] = useState(getSize());
      useEffect(() => {
      const handler = () => {
          setSize(getSize())
        };
        window.addEventListener('resize', handler);
        return () => {
          window.removeEventListener('resize', handler);
        };
      }, []);
      return size;
    };
    //函数组件中使用这个hook
    const Demo = () => {
      const size = useWindowSize();
      if (size === "small") return <SmallComponent />;
      else return <LargeComponent />;
    };
    • 有助于关注分离

    Hooks能够让针对同一个业务逻辑的代码尽可能聚合在一块,在Class组件中不得不吧同一个业务逻辑代码分散在类组件的不同的生命周期方法中

    React如何从Class方式转Hooks

    图解:左侧是 Class 组件,右侧是函数组件结合 Hooks。蓝色和黄色代表不同的业务功能

    Hooks如何保存组件状态和使用生命周期?

    React一共提供了10个HooksuseStateuseEffectuseCallbackuseMemouseRefuseContext等等

    1、useState:让函数具有维持状态的能力

    我们要遵循的一个原则就是:state 中永远不要保存可以通过计算得到的值,例如:

    • 从 props 传递过来的值。有时候 props 传递过来的值无法直接使用,而是要通过一定的计算后再在 UI 上展示,比如说排序。那么我们要做的就是每次用的时候,都重新排序一下,或者利用某些 cache 机制,而不是将结果直接放到 state 里。

    • 从 URL 中读到的值。比如有时需要读取 URL 中的参数,把它作为组件的一部分状态。那么我们可以在每次需要用的时候从 URL 中读取,而不是读出来直接放到 state 里。

    • 从 cookie、localStorage 中读取的值。通常来说,也是每次要用的时候直接去读取,而不是读出来后放到 state 里。

    2、useEffect:执行副作用

    副作用是指一段和当前执行结果无关的代码。比如说要修改函数外部的某个变量,要发起一个请求。形式:useEffect(callback, dependencies)。涵盖了componentDidMountcomponentDidUpdatecomponentWillUnmount三个生命周期方法。简而言之,useEffect 是每次组件 render 完后判断依赖并执行。

    使用useEffect应该注意的点:

    没有依赖项,则每次 render 后都会重新执行

    useEffect(()=>{
    	console.log('re-render')		//每次render完成一次后就执行
    })
    • 空数组作为依赖项,则只在首次执行时触发,对应到 Class 组件就是 componentDidMount

    useEffect(()=>{
      console.log('did mount')		//相当于componentDidMount
    },[])
    • 可以返回一个函数,用在组件销毁的时候做一些清理的操作

    const [size,setResize] = useState({})
    useEffect(()=>{
    	const handler = () => {
        setResize()
    	}
    	window.addEventListener('resize',handler)
    	return ()=>{
    		window.removeEventListener('resize',handler)
    	}
    },[])

    以上是“React如何从Class方式转Hooks”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI