Bluetom

why use hook?

Not magic,just array

组件化组织

  • hoc

    • 定义:已component为参数,包装成一个新组建

    • 缺点:hoc当组合多个的时候,代码维护及阅读成本指数上升。

      高阶组件对于使用者来说里面是黑盒的,数据公用逻辑处理怎么。这种就不适用hoc

  • render-props

    定义:通过一个函数将class组件的state作为props传递给纯函数组件

    缺点:嵌套较多,地狱回调。如何性能优化

生命周期就是个错误?

举个🌰,写一个绑定事件。当生命周期较多时,加上各种埋点逻辑,how 2 play?有没有更优的解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class SomeCompoent extends Component {

componetDidMount() {
const node = this.refs['myRef'];
node.addEventListener('mouseDown', handlerMouseDown);
node.addEventListener('mouseUp', handlerMouseUp)
}

...

componetWillunmount() {
const node = this.refs['myRef'];
node.removeEventListener('mouseDown', handlerMouseDown)
node.removeEventListener('mouseUp', handlerMouseUp)
}
}

编译体积

当今react组件化的两种种方式:

  • Stateless Function Component
  • Class Component
    拿一个react的Class Component做demo,编译前是以下代码
1
2
3
4
5
class MyComponentClass extends React.Component {
render() {
return <div>{this.props.name}</div>;
}
}

Function Component编译后

1
2
3
4
5
6
7
8
9
10
11
const MyStatelessComponent = props => <div>{props.name}</div>;


// after
var MyStatelessComponent = function MyStatelessComponent(props) {
return React.createElement(
"div",
null,
props.name
);
}

Class Component编译后,无比臃肿。hot reload性能也会变差

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var MyComponentClass = function (_React$Component) {
_inherits(MyComponentClass, _React$Component);
function MyComponentClass() {
_classCallCheck(this, MyComponentClass);
return _possibleConstructorReturn(this, (MyComponentClass.__proto__ || Object.getPrototypeOf(MyComponentClass)).apply(this, arguments));
}
_createClass(MyComponentClass, [{
key: "render",
value: function render() {
return React.createElement(
"div",
null,
this.props.name
);
}
}]);
return MyComponentClass;
}(React.Component);

functional component对比具体可以看这篇React: Class Component vs Functional Component

综上针对以下缺点

  • 编译体积大
  • 生命周期过多,维护成本高
  • 通过hoc包装组件,复杂组件会更多且阅读困难

hook应运而生。

hook做了什么

先看下他的基本api,分了三类

  • state hook:获取当前state
  • effect hook:可以让 function componet 使用生命周期和 side effect
  • custom hook:根据 react 提供的 useState、useReducer、useEffect、useRef等自定义自己需要的 hooks

9个hook列表如下:

  • useState
  • usEffect
  • useContext
  • useReducer
  • useCallback
  • useMemo
  • useRef
  • useImperativeHandle
  • useLayoutEffect

state hook

一个组件中,使用useState获取一个state值及对应的setState。入参是trigger默认值

1
2
3
4
5
6
7
8
9
10
11
12
const App = () => {
const [trigger, setTrigger] = useState(true);
const [mounted, setMount] = useState(true);
return (
<div>
<button onClick={() => setTrigger(!trigger)}>Trigger Update</button>
<button onClick={() => setMount(!mounted)}>Toggle Mount</button>

{mounted ? <Position /> : null}
</div>
);
};

effetc hook

useEffect等价于componentDidMount注册mousemove,返回的函数会在componentWillUnmount时触发

1
2
3
4
5
6
7
8
useEffect(() => {
window.addEventListener("mousemove", logMousePosition);
console.log("Created");
return () => {
console.log("Cleaned up");
window.removeEventListener("mousemove", logMousePosition);
};
};

useReducer

相当于实现了一个redux。入参一个action,initialState。返回当前state和dispatch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const initialState = {count: 0};

function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}

function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'increment'})}>+</button>
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
</>
);
}

Bluetom

作为挨踢业的前段湿 搬过砖也画过画:爱看、爱听、爱玩儿、爱折腾、爱打撸啊撸、intj

Proudly published with Hexo