[react] 无状态组件 与 高阶组件
高阶组件
通过函数和闭包,改变已有组件的行为,
本质上就是 Decorator 模式在React的一种实现。
- 定义
import { Component } from "React" ;
export const Enhance = (ComposedComponent) => {
return class extends Component {
constructor() {
this.state = { data: null };
}
componentDidMount() {
this.setState({ data: 'Hello' });
}
render() {
return <ComposedComponent {...this.props} data={this.state.data} />;
}
}
}
Enhance 是一个方法,当传入一个 Component(ComposedComponent) 的时候,
它将自动为该 Component 进行扩展并返回新的类定义。
Enhance 中就返回了一个扩展的 Component 类,为构造函数中添加了 state,
也在 React 生命周期函数 componentDidMount中添加了处理逻辑,
而 render 方法则使用了传入的参数,完成了渲染。
- 用法
import { Component } from "React";
import { Enhance } from "./Enhance";
class MyComponent = class extends Component {
render() {
if (!this.props.data) return <div>Waiting...</div>;
return <div>{this.props.data}</div>;
}
}
export default Enhance(MyComponent); // Enhanced component`
- 另一个例子
function connectPromise({promiseLoader, mapResultToProps}) {
return Comp=> {
return class AsyncComponent extends Component {
constructor(props) {
super();
this.state = {
result: undefined
}
}
componentDidMount() {
promiseLoader()
.then(result=> this.setState({result}))
}
render() {
return (
<Comp {...mapResultToProps(props)} {...this.props}/>
)
}
}
}
}
const UserList = connectPromise({
promiseLoader: loadUsers,
mapResultToProps: result=> ({list: result.userList})
})(List); //List can be a pure component
const BookList = connectPromise({
promiseLoader: loadBooks,
mapResultToProps: result=> ({list: result.bookList})
})(List);
无状态组件
findDOMNode和refs都无法用于无状态组件中,无状态组件挂载时只是方法调用,没有新建实例。
当无状态组件需要使用到生命周期时,可使用高阶组件包装。
function HelloComponent(props, /* context */) {
return <div>Hello {props.name}</div>
}
ReactDOM.render(<HelloComponent name="Sebastian" />, mountNode)
function Input({ label, name, value, ...props }, { defaultTheme }) {
const { theme, autoFocus, ...rootProps } = props
return (
<label
htmlFor={name}
children={label || defaultLabel}
{...rootProps}
>
<input
name={name}
type="text"
value={value || ''}
theme={theme || defaultTheme}
{...props}
/>
)}
Input.contextTypes = {defaultTheme: React.PropTypes.object};