evantianx / Bloooooooog

Place to record what I thought and learned
0 stars 0 forks source link

关于 React 的一切 #46

Open evantianx opened 7 years ago

evantianx commented 7 years ago

React 组件解耦要点

参考文章:

Techniques for decomposing React components

分离 render()

class Panel extends React.Component {
  renderHeading() {
    // ...
  }

  renderBody() {
    // ...
  }

  render() {
    return (
      <div>
        {this.renderHeading()}
        {this.renderBody()}
      </div>
    );
  }
}

但是上述方法只是分离了组件组装位置,其他属性仍然存在耦合,我们要彻底解耦的话,可以使用功能组件分离:

const PanelHeader = (props) => (
  // ...
);

const PanelBody = (props) => (
  // ...
);

class Panel extends React.Component {
  render() {
    return (
      <div>
        // Nice and explicit about which props are used
        <PanelHeader title={this.props.title}/>
        <PanelBody content={this.props.content}/>
      </div>
    );
  }
}
evantianx commented 6 years ago

Why you need keys for collections in React

文中提到几个点:

evantianx commented 6 years ago

How to better organize your React applications?

关于 React 大型项目的目录组织方式(按照特性而非文件类型来组织),值得一试

evantianx commented 6 years ago

React API 学习

setState()

setState() 并非即时更新,为了保证性能,React 会延时然后根据反馈更新。因此若要获得更新后的状态,有两种方法:

constructor(props)

React.Component创建子类时,若需要初始化 state 或绑定某些事件时,可以用 constructor(props) 来完成。

注意: 若使用到 this.props() 则需要在 constructor(props) 开头声明 super(props) ,否则 this.props 会为 undefined。

初始化 state ,赋给 this.state 值即可。

constructor(props) {
  super(props);
  this.state = {
    loading: true
  }
}

componentWillMount()

挂载组件发生前调用。

建议不要在其中添加副作用或者订阅,将这些添加入 componentDidMount()

由于是在 render() 前调用,所以在该方法中同步调用 setState() 并不会引起额外的重渲染。但是通常情况下建议在 constructor() 中调用 setState()

componentDidMount()

顾名思义,在组件挂载之后立即调用。

此时 DOM 节点已经创建完毕,因此任何需要依靠 DOM 的初始化工作应该在该方法中进行。同时也是实例化网络请求以及订阅等的绝佳之处。

在该方法中调用 setState() 会引起额外的渲染。但是可以保证虽然 render() 会被调用两次,用户不会看到中间的状态(TODO: how?)。注意这样通常会引起性能问题。

某些情况下不可避免要在 componentDidMount() 中调用 setState() 对 DOM 节点进行操作,如弹窗,提示框等。

shouldComponentUpdate(nextProps, nextState)

判断组件输出是否受当前 state 或 props 变化的影响。默认情况下返回 true,任何状态的变化都会引起组件的 re-render。 若返回 false,组件将不会再调用 componentWillUpdate()render()componentDidUpdate() 这三个方法。

调用时间:

当接收到新的 props 或者 state 时调用,且该调用发生在 render() 之前。

若为初次渲染或者调用了forceUpdate(),则该方法不会被调用。

对子组件 re-render 的影响:

返回 false 不会阻止状态发生变化的子组件的 re-render。

React.PureComponent

shouldComponentUpdate(nextProps, nextState) 的些微实现,之所以说是些微实现,是因为它在比较状态变化时只对 state 和 props 进行了浅比较。

比较

官方不建议在 shouldComponentUpdate() 中进行深比较,会引起性能问题。

componentWillReceiveProps(nextProps)

在已挂载组件接收到新的 props 时调用。 在挂载组件时不会调用 componentWillReceiveProps(nextProps) ,该方法只在 props 更新时调用。

注意:当 props 未发生改变时,React 也可能调用该方法,如父组件引起子组件 re-render 时。故一定要保证比较当前值和传过来的值。

componentWillUpdate(nextProps, nextState)

render() 之前调用。在首次渲染时不被调用。

注意:不能在 componentWillUpdate() 中调用 this.setState() 方法或者其他会引起更新的事件。

componentDidUpdate(prevProps, prevState)

在更新之后立即调用。首次渲染时不被调用。

主要用于组件更新后操作 DOM或者网络请求。

componentWillUnmount()

组件卸载或者销毁时调用。

一般用来清理在 componentDidMount() 中设置的定时器,网络请求或订阅等。

componentDidCatch(error, info)

React 16 中的新特性,参见 Error Handling in React 16

evantianx commented 6 years ago

组件数据共享

Share logic between components!

evantianx commented 6 years ago

React 项目组织方式

Three Rules For Structuring (Redux) Applications

三条准则

依特性划分目录

之前工作目录一般都是按照文件类型划分,如 actions、reducers 等。这样在开发某个特性的时候需要翻找相对应的目录,然后创建相对应文件,很麻烦。

依照特性划分,则会让你更专注于写代码,debugging 或者 refactoring 更加 ez。

各个 module 之间有明确的界限

避免循环依赖

The Anatomy Of A React & Redux Module (Applying The Three Rules) Additional Guidelines For (Redux) Project Structure

evantianx commented 6 years ago

React 生命周期

dz-97vzw4aabczj

Dan

online version

evantianx commented 5 years ago

关于事件绑定

若要在事件回调中使用 this 来获取到组件实例:

class Login extends React.Component {
  constructor(props) {
    super(props);
    this.onSubmit = this.onSubmit.bind(this)
  }

  onSubmit = () => {
    // do something
  }

  render() {
    return (
      <Button onClick={this.onSubmit}>Submit</Button>
    )
  }
}

为什么要进行这样的绑定?

This is why we need to bind event handlers in Class Components in React

主要原因就在于:

const a = 2
const obj = {
  a: 1,
  sayA() {
    console.log(this.a)
  }
}

const sayA = obj.sayA()  // 1

const sayAOtherWay = obj.sayA
sayAOtherWay() // 2  这就是 React 组件中调用事件回调的方式

而在 React 组件中不进行 bindthis 指向为 undefined 的原因在于:

The bodies of class declarations and class expressions are executed in strict mode, that is the constructor, static and prototype methods. Getter and setter functions are executed in strict mode.

evantianx commented 5 years ago

Redux-Saga

image

evantianx commented 5 years ago

React Fiber

The how and why on React’s usage of linked list in Fiber to walk the component’s tree