無狀態組件(Stateless Component) 是 React 0.14 之后推出的,大大增強了編寫 React 組件的方便性,也提升了整體的渲染性能。
無狀態組件 (Stateless Component)
function HelloComponent(props, /* context */) { return <div>Hello {props.name}</div>}ReactDOM.render(<HelloComponent name="Sebastian" />, mountNode)HelloComponent 第一個參數是 props,第二個是 context。最后一句也可以這么寫:
ReactDOM.render(HelloComponent{ name:"Sebastian" }, mountNode)可以看到,原本需要寫“類”定義(React.createClass 或者 class YourComponent extends React.Component)來創建自己組件的定義,現在被精簡成了只寫一個 render 函數。更值得一提的是,由于僅僅是一個無狀態函數,React 在渲染的時候也省掉了將“組件類” 實例化的過程。
結合 ES6 的解構賦值,可以讓代碼更精簡。例如下面這個 Input 組件:
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};這個 Input 組件(僅僅是示例)直接實現了 label/inputText 的組合:
無狀態組件用來實現 Server 端渲染也很方便,只要避免去直接訪問各種 DOM 方法。
無狀態組件與組件的生命周期方法
我們可以看到,無狀態組件就剩了一個 render 方法,因此也就沒有沒法實現組件的生命周期方法,例如 componentDidMount, componentWillUnmount 等。那么如果需要讓我們的 Input 組件能夠響應窗口大小的變化,那么該如何實現呢?這其實還是要引入“有狀態的組件”,只不過這個“有狀態的組件”可以不僅僅為 "Input" 組件服務。
const ExecutionEnvironment = require('react/lib/ExecutionEnvironment')const defaultViewport = { width: 1366, height: 768 }; // Default size for server-side renderingfunction withViewport(ComposedComponent) { return class Viewport extends React.Component { state = { // Server 端渲染和單元測試的時候可未必有 DOM 存在 viewport: ExecutionEnvironment.canUseDOM ? { width: window.innerWidth, height: window.innerHeight } : defaultViewport } componentDidMount() { // Server 端渲染是不會執行到 `componentDidMount` 的,只會執行到 `componentWillMount` window.addEventListener('resize', this.handleWindowResize) window.addEventListener('orientationchange', this.handleWindowResize) } componentWillUnmount() { window.removeEventListener('resize', this.handleWindowResize) window.removeEventListener('orientationchange', this.handleWindowResize) } render() { return <ComposedComponent {...this.props} viewport={this.state.viewport}/> } handleWindowResize() { const { viewport } = this.state if (viewport.width !== window.innerWidth || viewport.height !== window.innerHeight) { this.setState({ viewport: { width: window.innerWidth, height: window.innerHeight } }) } } }}
新聞熱點
疑難解答
圖片精選