![](https://oss.jqhtml.com/wp-content/uploads/2020/7/mQVrMb.png)
用心阅读,跟随codesandbox demo或运行源码,你将熟悉react各种组件的优缺点及用法,彻底熟悉react hook的用法,收益应该不小
大纲:
- react 不同组件用法。
- react hook 相比以前带来什么。
- react hook 的用法。
React 组件的发展
1. 功能(无状态)组件
Functional (Stateless) Component,功能组件也叫无状态组件,一般只负责渲染。
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
2. 类(有状态)组件
Class (Stateful) Component,类组件也是有状态组件,也可以叫容器组件。一般有交互逻辑和业务逻辑。
class Welcome extends React.Component {
state = {
name: ‘tori’,
}
componentDidMount() {
fetch(…);
…
}
render() {
return (
<>
<h1>Hello, {this.state.name}</h1>
<button onClick={() => this.setState({name: ‘007’})}>改名</button>
</>
);
}
}
3. 渲染组件
Presentational Component,和功能(无状态)组件类似。
const Hello = (props) => {
return (
<div>
<h1>Hello! {props.name}</h1>
</div>
)
}
总结:
- 函数组件一定是无状态组件,展示型组件一般是无状态组件;
- 类组件既可以是有状态组件,又可以是无状态组件;
- 容器型组件一般是有状态组件。
- 划分的原则概括为: 分而治之、高内聚、低耦合;
通过以上组件之间的组合能实现绝大部分需求。
4. 高阶组件
Higher order components (HOC)
HOC 主要是抽离状态,将重复的受控组件的逻辑抽离到高阶组件中,以新的props传给受控组件中,高阶组件中可以操作props传入受控组件。
开源库中常见的高阶组件:Redux的connect, react-router的withRouter等等。
Class HocFactory extends React.Component {
constructor(props) {
super(props)
}
// 操作props
…
render() {
const newProps = {…};
return (Component) => <Component {…newProps} />;
}
}
Const Authorized = (Component) => (permission) => {
return Class Authorized extends React.Component {
…
render() {
const isAuth = ‘’;
return isAuth ? <Component /> : <NoMatch />;
}
}
}
// 项目中涉及到的高阶组件
// 主要作用是将所有action通过高阶组件代理到component的Pro上。
import { bindActionCreators } from ‘redux’;
import { connect } from ‘react-redux';
// 所有页面action集合
import * as actions from './actions';
// 缓存actions, 避免render重新加载
let cachedActions;
// action通过bindActionCreators绑定dispatch,
const bindActions = (dispatch, ownProps) => {
if (!cachedActions) {
cachedActions = {
dispatch,
actions: bindActionCreators(actions, dispatch),
};
}
return cachedActions;
};
const connectWithActions = (
mapStateToProps,
mergeProps,
options
) => (component) => connect(
mapStateToProps, bindActions, mergeProps, options
)(component);
export default connectWithActions;
// 类似还有log中间件样子的等等。
HOC的不足
- HOC产生了许多无用的组件,加深了组件层级,性能和调试受影响。
- 多个HOC 同时嵌套,劫持props, 命名可能会冲突,且内部无法判断Props是来源于那个HOC。
5. Render Props
Render Props 你可以把它理解成 JavaScript 中的回调函数
// 实现一个控制modal visible的高阶组件
class ToggleVisible extends React.Component {
state = {
visible: false
};
toggle = () => {
this.setState({visible: !this.state.visible});
}
render() {
return (
<>{this.props.children({visible, toggle})}</>
);
}
}
//使用
const EditUser = () => (
<ToggleVisible>
{({visible, toggle}) => (<>
<Modal visible={visible}/>
<Button onClick={toggle}>打开/关闭modal</Button>
</>)}
</ToggleVisible>
)
优点
- 组件复用不会产生多余的节点,也就是不会产生多余的嵌套。
- 不用担心props命名问题。
6. 组合式组件(Compound Component)
子组件所需要的props在父组件会封装好,引用子组件的时候就没必要传递所有props了。组合组件核心的两个方法是React.Children.map和React.cloneElement。
例如下面 子组件需要的click事件转移到了父组件,通过父组件内部封装到子组件上,ant-design的很多group组件用到了此方法。
class GroupButton extends React.PureComponent {
state = {
activeIndex: 0
};
render() {
return (
<>
{React.Children.map(this.props.children, (child, index) =>
child.type
? React.cloneElement(child, {
active: this.state.activeIndex === index,
onClick: () => {
this.setState({ activeIndex: index });
this.props.onChange(child.props.value);
}
})
: child
)}
</>
);
}
}
// 用法
<GroupButton
onChange={e => {
console.log(“onChange”, e);
}}
>
<Button value="red">red</Button>
<Button value="yellow">yellow</Button>
<Button value=“blue”>blue</Button>
<Button value="white">white</Button>
</GroupButton>
废话结束,开始进入正题。。。
React hooks
Hook 出现之前,组件之间复用状态逻辑很难,解决方案(HOC、Render Props)都需要重新组织组件结构, 且代码难以理解。在React DevTools 中观察过 React 应用,你会发现由 providers,