阅读 5567

React Hooks 可以为我们带来什么,及为什么我觉得React才是前端的未来

简单说明一下,react hooks 是一个已经在提议中的新功能,预计会随着React 16.7.0一起发布。 /以上所述所有React均指ReactJS,下述会用React简称/

要明白什么是React Hooks,那可能先了解一下它的两个替代品HOCFaCC/Render Props

HOC(Higher-Order Components),React高阶组件

如果我们有一个需要共享的状态,需要在多个组件之间传递。我们会怎么做? 或者说,当多个组件有公用的部分的时候,我们会选择怎么做?

例如:

// ComponentA
import React, { Component } from "react";

export default class ComponentA extends Component {
  state = { toggle: false };
  click = () => {
    this.setState({ toggle: !this.state.toggle });
  };

  render() {
    const { toggle } = this.state;
    return (
      <div className="App">
        <button onClick={this.click}>Toggle Name</button>
        {toggle && <div>ComponentA</div>}
      </div>
    );
  }
}
复制代码

这里我们举一个极端的例子,让ComponentB和A做一样的事情

// ComponentB
export default class ComponentB extends Component {
  state = { toggle: false };
  click = () => {
    this.setState({ toggle: !this.state.toggle });
  };

  render() {
    const { toggle } = this.state;
    return (
      <div className="App">
        <button onClick={this.click}>Toggle Name</button>
        {toggle && <div>ComponentB</div>}
      </div>
    );
  }
}
复制代码

可以看到代码重复的部分非常多,只有文字显示的不同而已。 这里就需要用到HOC了。

使用HOC之后,变成

// ComponentA
import React, { Component } from "react";
import HOC from "./HOC";

class ComponentA extends Component {
  render() {
    return <div>ComponentA</div>;
  }
}

export default HOC(ComponentA);
复制代码

ComponentB同上。

这里HOC的写法就是提出共有的部分,接收一个Component进行渲染。

const HOC = WrapperComponent =>
  class HOC extends Component {
    state = { toggle: false };
    click = () => {
      this.setState({ toggle: !this.state.toggle });
    };

    render() {
      const { toggle } = this.state;
      return (
        <div className="App">
          <button onClick={this.click}>Toggle Name</button>
          {toggle && <WrapperComponent />}
        </div>
      );
    }
  };

export default HOC;
复制代码

可以发现,让公用的部分提取了出去,并且让代码看起来更简单舒服了一些。每一个组件只需要关注自己内部的状态,而公有的部分以及共享状态的部分就交给HOC去解决。 这样不论再加多少个类似的Component,都无需大量的写重复代码了。

FaCC(Function as Child Component)

原理和HOC差不多,只是运用到了一个叫做 children的react props 可以讲代码简化成

//ComponentA
export default class ComponentA extends Component {
  render() {
    return <FaCC>{toggle => toggle && <div>ComponentA</div>}</FaCC>;
  }
}
复制代码
//FACC
export default class FaCC extends Component {
  state = { toggle: false };
  click = () => {
    this.setState({ toggle: !this.state.toggle });
  };

  render() {
    const { toggle } = this.state;
    return (
      <div className="App">
        <button onClick={this.click}>Toggle Name</button>
        {this.props.children(toggle)}
      </div>
    );
  }
}
复制代码

Render Props是用的一样的方法,只是换了别的属性,不用children而已

那么HOC们,还能做什么?

通过上述的行为,我们已经发现了,它们可以共用很多部分的代码。 如果再深入思考一下,就可以想到,在复杂的业务逻辑里面,如果发送同一个API请求的haul,我们不应该在每一个独立component里面发送一个请求。因为它们共享了同一个state,这样会造成资源的浪费。 我们将HOC的部分代码更改一下,例如:

const HOC = WrapperComponent =>
  class HOC extends Component {
    state = { toggle: false, data: {} };
    fetchData = () => {
      fetch("/api", params).then(response => {
        const { data } = data;
        this.setState(data);
      });
    };
    componentDidMount(){
        this.fetchData();
    }

    render() {
   /*......*/
  };

export default HOC;
复制代码

React Hooks

在Hooks里面利用它的Effect,可以让我们使用到和Component一样的部分生命周期。 关于ReactHooks的详细介绍,我会在别的文章进行详细描述。 在这里,我想进行的是React Hooks,HOC,FACC的比较。

那么如果想实现上述功能,React Hooks会怎么做呢?

// Hooks
import { useState, useEffect } from "react";

const useHooks = () => {
  const [data, setData] = useState(null);

  const fetchData = () => {
    fetch("/api", params).then(response => {
      const { data } = data;
      setData(data);
    });
  };

// Effect,这里相当于componentDidMount
  useEffect(() => {
    fetchData();
  });

  return data;
};

export default useHooks;
复制代码

在Component中需要用到公用的这个data的时候,我们只需要这样做

  // 这一行便是调用data的方法了
    const data = Hooks();
    return <div>{data}</div>;
复制代码

ReactHooks的优点?

使用ReactHooks无需复杂的DOM结构。

使用HOC们,去除掉了重复应用的问题。 可是打开React Dev Tool,我们会发现,我们的DOM结构却也更复杂了。 从

变成

再到

更重要的原因是,我觉得ReactHooks写起来更加简单,易懂,易读。

我想通过上述的代码比对,不难得出这个结论。

试想一下,在一个庞大项目里面,广泛使用HOC们,会带来什么样的代码复杂度?

为什么我觉得React才是前端的未来

正如我在前文描述的那样,不论是HOC还是FACC/Render Props,都有自己的技术上手难度以及理解困难的地方。 但是React Hooks的出现解决了这些问题。

一定有人不赞同,不负责任的猜测大概原因如下

  1. 行业本身需要有一定的技术门槛,写法和理解的困难是个体本身的学习能力以及钻研程度的问题,框架不应该为此埋单。
  2. React hooks 本身从写法实现上来说,违背一些JS的规范和趋势,如纯函数。

我的解答如下

  1. 技术门槛不错,但是我觉得技术是用来改变生活的,而不是为了让部分人找到工作。就好比开车有职业赛车手,也有普通在道路上开车的司机。作为专业从事这个行业的人员来说,我们是应该钻研以及理解一门技术。但是,如果一个后端的同事,或者一个初创小团队,需要做一个这样的东西。我觉得,技术简洁好实现,对他们来说应该是一个吸引点。
  2. 很多库为了实现一些简洁的功能,都会出现这样或那样的“奇怪”写法,这点认同。但是,有时候是需要一些取舍。

而我认为目前前端框架里面,能察觉到用简单的方式来处理日趋复杂的业务,这件事的,Angular, Vue 都还没有做到。 Angular非常完整,但是学习曲线相对陡。 Vue正在面临整库重写。 只有React,用简单的方式来处理复杂业务,并且第三方库生态链非常庞大。

所以,我看好它。