# 1.遗忘点

1、不能在函数组件标签上使用ref属性,但可以在函数组件内部使用ref属性

2、新手学习 react 迷惑的点(opens new window)

3、this.props.children 指的是组件标签内的内容

4、dangerouslySetInnerHTML,style要是要双花括号

5、this.setState里面直接可以直接接收一个对象,也可以接收一个函数返回的对象,推荐用函数返回的对象,异步设置优化性能,如下

handleInputEnter = e => {
  const inputValue = e.target.value
  if (e.keyCode === 13 && inputValue) {
    this.setState(preState => {
      const lists = [...preState.lists, inputValue]
      return { lists, inputValue: '' }
    })
  }
}
handleInputChange = e => {
  // this.setState({ inputValue: e.target.value })
  // console.log(this)
  const inputValue = e.target.value
  this.setState(() => ({ inputValue }))
}

6、当stateprops发生变化时,自身的render函数都会重新执行,当父组件的render函数被执行时,它的子组件render都将被重新执行

7、JSX通过createElement->JS对象(虚拟DOM)->真实的DOM

8、如果数据更新后要通过ref获取更新后的DOM,需要把获取 DOM的代码写在setState的第二个参数里面,因为setState是异步的,类似VuenextTick 里面获取数据更新后的DOMsetState的第二个参数是一个function

this.setState(() => ({ name: 'xiaoming' }), () => {})

9、生命周期

componentWillReceiveProps的执行时机:

  • 组件要从父组件接收参数
  • 组件第一次存在于父组件中,不会执行
  • 如果这个组件之前已经存在于父组件中,才会执行

componentWillMount->render->componentDidMount 执行顺序类似VuebeforeMount->render->mounted

父子组件执行顺序同Vuefater will mount->child will mount->child did mount->fater did mount

componentWillUpdate->render->componentDidUpdate 执行顺序类似VuebeforeUpdate->render->updated

每个阶段所的事情见链接(opens new window)

10、react 中性能优化

  • 方法在 constructor 中绑定 this
  • 多次 setState 合并成一次
  • shouldComponentUpdate 做是否更新判断

11、animation: forwards 保留动画的最后一帧

12、transition/transition-group使用注意点

注意: `transition`中`key`的使用问题

transition标签上面的key不能使用index,否则可能会出现数据和页面展示不同步的情况

代码(opens new window)

13、action / reducer / dispatch

aciton 的定义在dispatch中使用 action-type可以在reducer中使用

14、使用redux-saga

import { put, takeEvery } from 'redux-saga/effects'

put 接收的参数格式和 store.dispatch 的格式一致

typeEvery 第一个参数接收的的 action-type 中定义的字符串参数

15、mapStateToProps/mapDispatchToProps都是一个函数,返回一个对象

16、redux-thunkaction 可以返回一个函数,用于发送异步请求,见代码(opens new window)

17、immutable 同时设置多个值

actions 中写法:

const setHotSearch = hotSearch => {
  return {
    type: actionsType.HEADER_HOT_SEARCH,
    hotSearch: fromJS(hotSearch),
    totalPage: Math.ceil(hotSearch.length / 10),
  }
}

reducers中用merge方法避免写链式set,代码如下:

case actionsType.HEADER_HOT_SEARCH:
  return state.merge({
    hotSearch: action.hotSearch,
    totalPage: action.totalPage
  })

18、经过immutable包装的数组取出来遍历的时候需要用toJS()方法转回普通的 js 对象,代码示例:

let searchItems = []
let newList = hotSearch.toJS()
if (newList.length) {
  for (let index = (page - 1) * 10; index < page * 10; index++) {
    if (newList[index]) {
      searchItems.push(
        <span className="search-keyword-item" key={newList[index]}>
          {newList[index]}
        </span>
      )
    }
  }
}

19、transfromrotate只对块级元素有效,要是iconfont生效必须设置display:block

20、子元素浮动,可在父元素上添加overflow:hidden使得父元素感受到子元素的高度

21、受控组件与非受控组件

22、react-router-dom

23、hooks 的优势

  • 函数组件无 this 问题
  • 自定义 hook 方便复用状态逻辑
  • 副作用关注点分离

24、memo 与 useMemo 的区别

25、useCallback 针对的是给组件传递函数导致组件重新渲染问题优化

26 、类型校验的写法


class TodoItem{}

TodoItem.propTypes = {
  content: PropTypes.string
}

TodoItem.defaultProps = {
  test: 'hhhh'
}

class TodoItem{
  static defaultProps = {
    test:'hhhh'
  }
  
  static propTypes = {
    test:PropTypes.string
  }
}

  1. forwardRef用来访问子组件内部的DOM