ReactCollect icon indicating copy to clipboard operation
ReactCollect copied to clipboard

关于react无状态组件(函数式组件)

Open ckinmind opened this issue 8 years ago • 8 comments

函数式组件与基于Class声明的组件相比,其具有以下特性

  • 不需要声明类,可以避免大量的譬如extends或者constructor这样的代码
  • 不需要显示声明this关键字,在ES6的类声明中往往需要将函数的this关键字绑定到当前作用域,而因为函数式声明的特性,我们不需要再强制绑定

写法:

//es5
class Text extends React.Component {
  render() {
    return <p>{this.props.children}</p>;
  }
}

//函数式声明组件
const Text = (props) =>
  <p>{props.children}</p>;

函数式声明组件可以不用绑定this

这种无状态函数式组件的写法也是支持设置默认的Props类型与值的

const Text = ({ children }) => 
  <p>{children}</p>
Text.propTypes = { children: React.PropTypes.string };
Text.defaultProps = { children: 'Hello World!' };

另外,在无状态的组件函数中,我们也是可以访问Context的

const Text = (props, context) =>
  <p style={context}>props.children</p>;
Text.contextTypes = {
  fontFamily: React.PropTypes.string
};
class App extends React.Component {
  static childContextTypes = {
    fontFamily: React.PropTypes.string
  }
  getChildContext() {
    return {
      fontFamily: 'Helvetica Neue'
    };
  }
  render() {
    return <Text>Hello World</Text>;
  }
}

ckinmind avatar Jan 14 '17 08:01 ckinmind

例子1: 改写前:

class ReactFormLabel extends React.Component {
    constructor() {
        super();
    }
    render() {
        return(
            <label htmlFor={this.props.htmlFor}>{this.props.title}</label>
        )
    }
}

改写后:

const ReactFormLabel = (props) =>(
    <label htmlFor={props.htmlFor}>{props.title}</label>
);

单行的括号可以省略

const ReactFormLabel = (props) => 
    <label htmlFor={props.htmlFor}>{props.title}</label>;
  1. this可以省略
  2. 注意label的for标签要写成htmlFor

通过对象的解构赋值,还可以写成这样

const ReactFormLabel = ({ htmlFor, title }) =>
    <label htmlFor={htmlFor}>{title}</label>;

无状态组件也是支持设置默认的Props类型与值

const ReactFormLabel = (props) =>
    <label htmlFor={props.htmlFor}>{props.title}</label>;

ReactFormLabel.propTypes = {
    title: React.PropTypes.string,
    htmlFor: React.PropTypes.string
};

ckinmind avatar Jan 18 '17 14:01 ckinmind

看到一句话我们会使用函数式无状态组件除非需要本地 state 或生命周期函数的场景

这句话透露出什么状况下适合使用函数式组件:

  1. 无需state, 即不处理用户的输入,组件的所有的数据都是依赖props传入的
  2. 不需要用到生命周期函数

ckinmind avatar Jan 22 '17 12:01 ckinmind

@ckinmind 那如果使用redux和mobx呢?

yunshuipiao avatar Jan 10 '18 08:01 yunshuipiao

@yunshuipiao redux和无状态组件没关系, 至于mobx中无状态组件的写法参照这里

ckinmind avatar Jan 10 '18 08:01 ckinmind

@ckinmind 上面说需要本地 state是一种什么样的情况。 此时的state改变是否可以用redux或者mobx来达到同样的效果?

yunshuipiao avatar Jan 10 '18 08:01 yunshuipiao

@yunshuipiao 需要本地state的意思意思应该是如果这个组件也需要state去缓存一些数据,那个这个组件就不适合无状态组件的写法,无状态组件指的是那些只需要通过props传入数据然后简单展示的组件

ckinmind avatar Jan 10 '18 15:01 ckinmind

Hook出现后,就可以在无状态组件中使用state了,并且可以使用相应的Hook达到生命周期函数的效果

ducaoya avatar Jul 30 '21 01:07 ducaoya