react 常见问题总结

739 阅读6分钟

一、基本知识点

jsx 语法与html 差异

1、class 需要用 className 代替

2、label 中的for 需要 htmlFor 代替

3、style 值以对象形式使用

4、渲染列表以map 遍历

react 中文文档

菜鸟教程 react

react 组件分类

class组件 与 函数组件

class组件:通过class 生命并且继承 react.Component 的组件

class StatefulComponent extends Component {

    constructor(props) {
        super(props);
        this.state = {
            //定义状态
        }
    }

    render() {
        return (
            //render
        );
    }
}

函数组件:通过function 声明,并且不继承react.Component 的组件 的普通函数组件

有状态组件与无状态组件

有状态组件:在无状态组件的基础上,如果组件内部包含状态(state)且状态随着事件或者外部的消息而发生改变的时候,这就构成了有状态组件(Stateful Component)。有状态组件通常会带有生命周期(lifecycle),用以在不同的时刻触发状态的更新。

class StatefulComponent extends Component {

    constructor(props) {
        super(props);
        this.state = {
            //定义状态
        }
    }

    componentWillMount() {
        //do something
    }
  
    componentDidMount() {
        //do something
    }
    ... //其他生命周期

    render() {
        return (
            //render
        );
    }
}

无状态组件:无状态组件(Stateless Component)是最基础的组件形式,由于没有状态的影响所以就是纯静态展示的作用。一般来说,各种UI库里也是最开始会开发的组件类别。如按钮、标签、输入框等。它的基本组成结构就是属性(props)加上一个渲染函数(render)。由于不涉及到状态的更新,所以这种组件的复用性也最强。

const PureComponent = (props) => (
    <div>
        //use props
    </div>
)

容器组件与渲染组件

容器型组件:主要是组件是如何工作的,更具体的就是数据是怎么更新的,不包含任何的virtual dom(虚拟dom)的修改和组合,只关心数据的更新,不在乎dom是什么样的

import React from 'react'
import ReactDom from 'react-dom'
import RootTable from './RootTable' //引入展示型组件
class RootSearch extends React.Component{
  constructor(props){
    this.state = {id:'',name:'',nikeName:''}
  }
  componentDidMount(){
    this.axios.get('/user',{params:{id:2123}}).then((res)=>{
        this.setState({
        id:res.data.id,
        name:res.data.name,
        nikeName:res.data.nikeName
      })
    })
  }
    render(
    <div>
        <RootTable id={this.state.id} name={this.state.name} />
     </div>
  )
}

展示型组件:其主要的就是组件要怎么渲染,对virtual Dom具体是怎么操作的,也包含样式的修改组合,同时,它不依赖任何形式的store

const UIcomponent = (props) =(
    <div>
    {props.dataSource.map(callbackfn:item=>(
        <p onClick={()=>props.onClick(item)} >item.userName</p>
     ))}
  </div>
)

高阶组件

高阶组件(HOC) 是react中用于重用组件逻辑的高级技术。HOC本身不是ReactAPI的一部分,他们是从react构思本质中浮现出来的一种模式。具体来说,高阶组件是一个函数,能够接受一个组件并返回一个新组件

高阶函数就是一个函数,但 参数 和 返回值 为 函数。

高阶组件也是一个函数,但 参数 和 返回值 为 组件。

理解react 生命周期

React 16之后有三个生命周期被废弃:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

因为这些生命周期方法容易被误解和滥用。

React 16.8+的生命周期分为三个阶段,分别是挂载阶段、更新阶段、卸载阶段。

挂载阶段

  • constructor: 构造函数,最先被执行,我们通常在构造函数里初始化state对象或者给自定义方法绑定this
  • getDerivedStateFromProps: static getDerivedStateFromProps(nextProps, prevState),这是个静态方法,当我们接收到新的属性想去修改state,可以使用getDerivedStateFromProps
  • render: render函数是纯函数,只返回需要渲染的东西,不应该包含其它的业务逻辑,可以返回原生的DOM、React组件、Fragment、Portals、字符串和数字、Boolean和null等内容
  • componentDidMount: 组件装载之后调用,此时可以获取到DOM节点并操作,比如对canvas,svg的操作,服务器请求,订阅都可以写在这个里面,但是记得在componentWillUnmount中取消订阅。

更新阶段

  • getDerivedStateFromProps: 此方法在更新个挂载阶段都可能会调用
  • shouldComponentUpdate: shouldComponentUpdate(nextProps, nextState),有两个参数nextPropsnextState,表示新的属性和变化之后的state,返回一个布尔值,true表示会触发重新渲染,false表示不会触发重新渲染,默认返回true,我们通常利用此生命周期来优化React程序性能
  • render: 更新阶段也会触发此生命周期
  • getSnapshotBeforeUpdate: getSnapshotBeforeUpdate(prevProps, prevState),这个方法在render之后,componentDidUpdate之前调用,有两个参数prevPropsprevState,表示之前的属性和之前的state,这个函数有一个返回值,会作为第三个参数传给componentDidUpdate,如果你不想要返回值,可以返回null,此生命周期必须与componentDidUpdate搭配使用
  • componentDidUpdate: componentDidUpdate(prevProps, prevState, snapshot),该方法在getSnapshotBeforeUpdate方法之后被调用,有三个参数prevPropsprevStatesnapshot,表示之前的props,之前的state,和snapshot。第三个参数是getSnapshotBeforeUpdate返回的,如果触发某些回调函数时需要用到 DOM 元素的状态,则将对比或计算的过程迁移至getSnapshotBeforeUpdate,然后在 componentDidUpdate中统一触发回调或更新状态。

卸载阶段

  • componentWillUnmount: 当组件被卸载或者销毁了就会调用,我们可以在这个函数里去清除一些定时器,取消网络请求,清理无效的DOM元素等垃圾清理工作。

react-router 与 react-router-dom

常用hooks

参考文档

React Hooks 的意思是,组件尽量写成纯函数,如果需要外部功能和副作用,就用钩子把外部代码"钩"进来。 而React Hooks 就是我们所说的“钩子”。

四种最常用钩子

  • useState()
  • useContext()
  • useReducer()
  • useEffect()

不同的钩子为函数引入不同的外部功能,我们发现上面四种钩子都带有use前缀,React约定,钩子一律使用 use前缀命名。所以,你自己定义的钩子都要命名为useXXX。

useState()

import React, {useState} from 'react'
const AddCount = () => {
    // 设置默认值,并提供修改方法
  const [ count, setCount ] = useState(0)
  const addcount = () => {
    let newCount = count
    setCount(newCount+=1)
  } 
  return (
    <>
      <p>{count}</p>
      <button onClick={addcount}>count++</button>
    </>
  )
}
export default AddCount 

  • useContext():共享状态钩子

该钩子的作用是,在组件之间共享状态。关于Context这里不再赘述,其作用就是可以做状态的分发,在React16.X以后支持,避免了react逐层通过Props传递数据。 下面是一个例子,现在假设有A组件和B组件需要共享一个状态。

useReducer()

做状态管理

useEffect

useEffect()接受两个参数,第一个参数是你要进行的异步操作,第二个参数是一个数组,用来给出Effect的依赖项。只要这个数组发生变化,useEffect()就会执行。当第二项省略不填时,useEffect()会在每次组件渲染时执行。这一点类似于类组件的componentDidMount

redux 与 react-redux

参考文档1

参考文档2