参考文献:
一些比较经典对于hooks的介绍
Hooks are fully encapsulated — each time you call a Hook, it gets isolated local state within the currently executing component. This doesn’t matter for this particular example (window width is the same for all components!), but it’s what makes Hooks so powerful. They’re not a way to share state — but a way to share stateful logic. We don’t want to break the top-down data flow!
What is a Hook? A Hook is a special function that lets you “hook into” React features. For example, useState is a Hook that lets you add React state to function components.
function MyResponsiveComponent() {
const width = useWindowWidth(); // Our custom Hook
return (
<p>Window width is {width}</p>
);
}
function useWindowWidth() {
const [width, setWidth] = useState(window.innerWidth);
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth);
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
});
return width;
}
They’re not a way to share state — but a way to share stateful logic., 这句话就是hooks的精髓所在,hooks是一种分享状态逻辑的方式,而不是分享状态。上面的小例子就可以说明这句话。
在之前的react版本中,如果你想在不同的components之间分享状态逻辑,就必须使用hoc或者render props等方式,这就导致组件嵌套很深。让我想起了我们公司业务为了开发遮罩层方便就使用了hoc这种方式去分享状态逻辑。这样就可以不用每一个遮罩层都要去写防滚动穿透,关闭和开启等问题。但是如果使用hooks就不用嵌套一层组件,而且你的组件就可以直接使用函数式组件
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import React, {Component} from 'react'
import {bindActionCreators} from 'redux'
import * as Actions from '../../actions'
import hoistNonReactStatic from 'hoist-non-react-statics'
export default function hocModal(WrappedComponent, backStyle) {
class EnhanceModal extends Component {
constructor(props) {
super(props)
this.cover = null
this.passiveSupported = false
this.handleClose = this.handleClose.bind(this)
}
componentWillUnmount() {
const {actions} = this.props
actions.hideModal()
}
handleClose(e) {
if(e.target.dataset.name === 'modal') {
const {actions} = this.props
actions.hideModal()
}
}
handleTouchMove(e) {
// e.stopPropagation()
e.preventDefault()
}
render() {
const {modal, modalKey} = this.props
return modal.isOpen && modal.openKey === modalKey
? <div ref={cover => this.cover = cover} className="modal-mask" onClick={this.handleClose} data-name="modal" style={backStyle}>
<WrappedComponent {...this.props} />
</div>
: null
}
}
/**
* 以下是配置高阶组件的相关属性。便于错误处理以及调试。
*/
//为高阶组件设置displayName
const WrappedComponentName = WrappedComponent.displayName
|| WrappedComponent.name
|| 'Component'
EnhanceModal.displayName = `hocModal(${WrappedComponentName})`
//将WrapComponent的必要static方法注入Enhance中
hoistNonReactStatic(EnhanceModal, WrappedComponent)
EnhanceModal.defaultProps = {
supportTouchMove: false,
}
//在connect之前进行type指定,保障指定的是EnhanceModal,否则就是Connect组件的属性了
EnhanceModal.propTypes = {
modal: PropTypes.object.isRequired,
actions: PropTypes.object.isRequired,
modalKey: PropTypes.string.isRequired,
supportTouchMove: PropTypes.bool.isRequired,
}
//在组建内部获取props,减少组件调用props设置
EnhanceModal = connect(state => ({modal: state.modal}), dispatch => {
return {
actions: bindActionCreators(Actions, dispatch)
}
})(EnhanceModal)
return EnhanceModal
}
useEffect以及React生命周期
本段落直接来自 对React Hooks的一些思考
精简生命周期函数,合并mount和update。
了解React源码的人,肯定都比较了解:mount和update在react内部是都当update来处理的。useEffect的出现,预示了react官方精简生命周期函数的方向。
官方在推出这一API时,也告诉了大家一个事实,React团队将倾向于把componentDidMount和componentDidUpdate不作区分。
事实上,React团队早就有了这一倾向,并通过先前版本的API向开发者传达了这一信号,那就是用getDerivedStateFromProps替代componentWillReceiveProps。
在componentWillReceiveProps的时代,组件的state其实根据生命周期阶段的不同,是有2个不同的计算方法的:
- 在mount之前,推荐在构造函数中通过props参数来计算state,并直接赋值为this.state。
- 在mount之后,使用componentWillReceiveProps来计算并使用setState进行更新。
而getDerivedStateFromProps作为一个静态方法,根本没有区别这两者,它是唯一的“通过props计算state”的入口。
将组件的状态分为2部分,一部分为自己生成自己管理的自治状态(owned),另一部分为由props计算得来的衍生状态(derived)。在初始化状态时,仅初始化自治状态,将原生状态赋为null,并在getDerivedStateFromProps中再进行初始化(即便在构造函数中可以完成衍生状态的计算)。
网友评论