React Learning Notes _ stateless components (stateless Component) and higher-order components

Source: Internet
Author: User
Stateless component and higher-order components
Stateless Component was introduced after React 0.14, which greatly enhanced the convenience of writing React components and also improved the overall rendering performance. I. Stateless Component

function HelloComponent (props, / * context * /) {
  return <div> Hello {props.name} </ div>
}
ReactDOM.render (<HelloComponent name = "Sebastian" />, mountNode)
The first parameter of HelloComponent is props and the second is context. The last sentence can also be written like this:

ReactDOM.render (HelloComponent {name: "Sebastian"}, mountNode)
As you can see, you originally needed to write a "class" definition (React.createClass or class YourComponent extends React.Component) to create your own component definition. Now it has been reduced to writing only one render function. It is worth mentioning that, because it is only a stateless function, React also saves the process of instantiating the "component class" when rendering.

Combined with ES6's destructuring assignment, you can make your code more streamlined. For example, the following Input component:

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};

This Input component (just an example) directly implements the label / inputText combination: defaultTheme is deconstructed from the Context. If the props do not set a theme, the defaultTheme will be used instead. autoFocus needs to be passed to the underlying inputText and not left to the label at the same time, so it will be taken out through {theme, autoFocus, ... rootProps} = props first.

Stateless components are also very convenient for server-side rendering, as long as you avoid directly accessing various DOM methods. 2. Stateless components and component lifecycle methods

We can see that there is only one render method left for stateless components, so there is no way to implement component lifecycle methods, such as componentDidMount, componentWillUnmount etc. So if we need our Input component to be able to respond to changes in the window size, how do we do that? This is actually to introduce a "stateful component", but this "stateful component" can serve more than just the "Input" component.

const ExecutionEnvironment = require ('react / lib / ExecutionEnvironment')
let viewport = {width: 1366, height: 768}; // Default size for server-side rendering

function handleWindowResize () {
  if (viewport.width! == window.innerWidth || viewport.height! == window.innerHeight) {
    viewport = {width: window.innerWidth, height: window.innerHeight}
  }
}

function withViewport (ComposedComponent) {
  return class Viewport extends React.Component {
    state = {
      // DOM may not be present during server-side rendering and unit testing
      viewport: ExecutionEnvironment.canUseDOM?
        {width: window.innerWidth, height: window.innerHeight}: viewport
    }
    componentDidMount () {
      // Server-side rendering will not be performed to `componentDidMount`, only to` componentWillMount`
      window.addEventListener ('resize', handleWindowResize)
      window.addEventListener ('orientationchange', handleWindowResize)
    }
    componentWillUnmount () {
      window.removeEventListener ('resize', handleWindowResize)
      window.removeEventListener ('orientationchange', handleWindowResize)
    }
    render () {
      return <ComposedComponent {... this.props} viewport = {this.state.viewport} />
    }
  }
}
Then, we can create an Input component that has a chance to respond to the change in window size:

const SizeableInput = withViewport (Input)
ReactDOM.render (<SizeableInput name = "username" label = "Username" {... props} />, mountNode)
withViewort as a "high-order component" is not just for Input services. It can add a viewport property to any component you need, and trigger a redraw when the window size changes.

If you have used Redux, you should also be familiar with the use of "connect decorator". "connect decorator" is also a high-level component, so you can continue to "patch up":

const UserNameInput = connect (
  state => ({value: state.username})
) (SizeableInput)
The existence of higher-order components has two benefits: When it says that stateless components are written, one day it is found that state processing is needed, so there is no need to completely rework :) Often when we need state, this requirement can be reused, For example, withViewport above can be used to add the viewport attribute to other components (whether or not they are stateless components).

Higher-order components plus stateless components greatly enhance the testability and maintainability of the entire code. At the same time, we are constantly "inducing" us to write better code. Third, stateless components do not support "ref"

It's a shame that stateless components don't support "ref". The principle is simple, because there is no instantiation process before React calls the method of the stateless component, so there is no so-called "ref".

The combination of ref and findDOMNode actually breaks the convention of passing state between parent and child components through props only. It is dangerous and dirty and needs to be avoided. Four, stateless components do not yet support Hot Module Replacement for babel-plugin-react-transform
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.