美文网首页
react拓展

react拓展

作者: 一号聪明 | 来源:发表于2022-01-14 17:14 被阅读0次

setState()

setState更新状态的2种方式

  1. 对象式的setState
setState(stateChange,[callback])

1. stateChange为状态改变对象
2. callback是可选的回调函数,它在状态更新完毕,界面也更新后(render调用后)才被调用
  1. 函数式的setState
setState(updater, [callback])
1. updater为返回stateChange对象的函数
2. updater可以接收到state和props
3. callback是可选的回调函数,它在状态更新、界面更新后(render调用后)才被调用

state = { count: 0 }

add = () => {
  // 对象式的setState
  const { count } = this.state // 0
  this.setState({ count: count + 1}, () => {
    console.log(this.state.count) // 1
  })
    console.log(this.state.count) // 0
  
  // 函数式编程
  /*
  this.setState((state,props) => {
    return {
      count: state.count + 1
    } 
  })
  **/
  this.setState(state => ({count: state.count + 1}))
  
}

对象式的setState是函数式的setState的简写方式

使用原则:

1.如果新状态不依赖于原状态 ====> 使用对象方式

2.如果新状态依赖于原状态 =====> 使用函数方式

3.如果需要在setState()执行后获取最新的状态数据,需要在第二个callback函数中读取

lazyLoad

路由组件的lazyLoad

import React, { Component, lazy, Suspense } from 'react'

const Loading from './Loading'
const Home = lazy(() => import('./Home'))
const About = lazy(() => import('./About'))


<Suspense fallback={<Loading />}>
  {/* 注册组件 */}
    <Route path="/about" component={About}>
  <Route path="/home" component={Home}>
</Suspense>


Hooks

React Hook/Hooks是什么?

  1. Hook是React 16.8.0版本增加的新特性/语法
  2. 可以使在函数组件中使用state以及其他的React特性

三个常用的Hook

  1. State Hook:React.useState()

    1. State Hook 让函数组件也可以有state状态,并进行状态数据的读写操作

    2. 语法:const [xxx, setXxx] = React.useState(initValue)

    3. useState()说明

      1. 参数:第一次初始化制定的值在内部做换粗
      2. 返回值:包含2个元素的数组,第一个为内部值当前状态值,第二个为更新状态值的函数
    4. setXxx()的2种写法:

      1. setXxx(newValue):参数为非函数值,直接指定新的状态值,内部用其覆盖原来的值
      2. setXxx(value => newValue):参数作为函数,接受原本的状态值,返回新的状态值,内部用其覆盖原来的状态值
    5. function Test () {
          console.log('Test组件')
          const [count, setCount] = React.useState(0)
          const [name, setName] = React.useState('tom')
          function add () {
              // setCount(count + 1) // 第一种写法
              setCount(count => count + 1)
          }
          function changeName() {
              setName('jack')
          }
          return(
              <div>
                  <h1>Hooks</h1>
                  <h2>当前数值为{ count }</h2>
                  <p>我的名字是:{ name }</p>
                  <button onClick={add}>增加</button>
                  <button onClick={changeName}>更改名称</button>
              </div>
          )
      }
      export default Test
      
  2. Effect Hook:React.useEffect()

    1. Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)

    2. React中的副作用操作

      1. 发送ajax操作
      2. 设置订阅/启动定时器
      3. 手动更改真实DOM
    3. 语法说明:

      1. useEffect(() => {
           // 在此可以执行任何带副作用的操作
          return () => {
            // 在此做一些收尾工作,比如:清除定时器/取消订阅等
          }
        },[stateValue]) // 如果制定的是[],回调函数只会在第一次render()后执行
        
      2. 可以把 useEffect Hook 看做如下三个函数的组合

        1. componentDidMount()
          componentDidUpdate()
          componentWillUnmount()
          
      3. function Test () {
            console.log('Test组件')
            const [count, setCount] = React.useState(0)
            React.useEffect(() => {
                let timer = setInterval(() => {
                    setCount(count => count + 1)
                }, 1000);
                return () => {
                    console.log('卸载组件####')
                    clearInterval(timer)
                }
            },[])
            function unMount() {
                reactDom.unmountComponentAtNode(document.getElementById('root'))
            }
            return(
                <div>
                    <h1>Hooks</h1>
                    <h2>当前求和为{ count }</h2>
                    <button onClick={unMount}>卸载组件</button>
                </div>
            )
        }
        
  3. Ref Hook

    1. Ref Hook 可以在函数组件中存储/查找组件内的标签或任意其他数据
    2. 语法:const refContainer = React.useRef()
    3. 作用:保存标签对象,功能与React.createRef() 一样
function Test () {
    const refContainer = React.useRef()
    function show() {
        alert(refContainer.current.value)
    }
    return(
        <div>
            <input type="text" ref={ refContainer } />
            <button onClick={ show }>点击提示当前输入内容</button>
        </div>
    )
}

Fragment

可以不用必须有一个真实DOM根标签了

<Fragment>
        <input type="test" />
    <input type="test" />
</Fragment>

// 编译后
<input type="test" />
<input type="test" />

Context

一种组件间通信方式,常用于[祖组件]与[后代组件]间通信,一般都用于封装react插件

使用:

import React, { Component } from 'react'

// 创建一个Context对象
const MyContext = React.createContext()
const { Provider, Consumer } = MyContext
export default class ContextComponent extends Component {
    state = { userName: '张三', age: 18 }
    render() {
        const { userName, age } = this.state
        return (
            <div>
                <h2>Context</h2>
                <Provider value={{userName, age}}>
                    <A />
                </Provider>   
            </div>
        )
    }
}

class A extends Component {
    render() {
        return(
            <div>
                <h3>我是a组件</h3>
                <B />
            </div>
        )
    }
}

class B extends Component {
    state = { userName: 'tom' }
    render() {
        return(
            <div>
                <h4>我是B组件</h4>
                <C1 />
                <C2 />
            </div>
        )
    }
}

// 类式组件
class C1 extends Component {
    // 声明context
    static contextType = MyContext
    state = { userName: 'tom' }
    render() {
        return(
            <div>
                <h5>我是C1组件</h5>
                <h5>Context接收到的用户名:{ this.context.userName }, 年龄:{ this.context.age }</h5>
            </div>
        )
    }
}

// 函数组件、类式组件都可以
function C2 () {
    return(
        <div>
            <h5>我是C2组件</h5>
            <h5>Context接收到的
                
                <Consumer>
                    {/* value 就是 context 中的 value 数据 */}
                    { value => `用户名:${ value.userName },年龄:${ value.age }` }
                </Consumer>
            </h5>
        </div>
    )
}

组件优化

component的2个问题

  1. 只要执行setState(),即使不改变状态数据,组件也会重新render()
  2. 当前组件重新render(),会自动重新render()子组件,即使没使用父组件的任何数据 ===> 效率低

效率高的做法

只有当组件的state或props数据发生改变时才重新render()

原因

component中的shouldComponentUpdate()总是返回true

  1. 解决一:重写shouldComponentUpdate()方法,比较新旧state或props数据,如果有变化才返回true,如果没有返回false
export default class Car extends Component {
    state = { carName: '奔驰63' }
    changeCar = () => {
        this.setState({
            carName: '迈巴赫'
        })
    }
    shouldComponentUpdate(nextProps, nextState) {
        console.log(this.props, this.state) // 当前props和state
        console.log(nextProps, nextState) // 接下来要变化的props和state
        return !this.state.carName === nextState.carName
    }
    render() {
        console.log('Car-parent render')
        const { carName } = this.state
        return (
            <div>
                <h3>我是Parent组件</h3>
                <p>我的车名字时:{carName}</p>
                <button onClick={this.changeCar}>点击换车</button>
                <Child carName={carName} />
            </div>
        )
    }
}

class Child extends Component {
    render() {
        console.log('Car-child render')
        const { carName } = this.props
        return (
            <div>
                <h4>我是Child组件</h4>
                <p>我接到的车是:{ carName }</p>
            </div>
        )
    }
}
  1. 解决二:使用PureComponent,PureComponent重写了shouldComponentUpdate(),只有state或props数据有变化才返回true
import React, { PureComponent } from 'react'

export default class Car extends PureComponent {
    state = { carName: '奔驰63' }
    changeCar = () => {
        this.setState({
            carName: '迈巴赫'
        })
    }
    render() {
        console.log('Car-parent render')
        const { carName } = this.state
        return (
            <div>
                <h3>我是Parent组件</h3>
                <p>我的车名字时:{carName}</p>
                <button onClick={this.changeCar}>点击换车</button>
                <Child carName={carName} />
            </div>
        )
    }
}

class Child extends PureComponent {
    render() {
        console.log('Car-child render')
        const { carName } = this.props
        return (
            <div>
                <h4>我是Child组件</h4>
                <p>我接到的车是:{ carName }</p>
            </div>
        )
    }
}

注意⚠️: 只是进行state和props数据的浅比较,如果只是数据对象内部数据变了,返回false。不能直接修改state数据,而是要产生新数据。项目中一般使用PureComponent来优化

render props

  1. children props:通过组件标签体传入结构

    1. <A>
        <B></B>
      </A>
      
      { this.props.children } // 如果B组件需要A组件内的数据  ===> 做不到
      
  2. Render props:通过组件标签属性传入结构,一般使用render函数属性

    1. <A render={ (data) => <C data ={ data }></C>}></A>
      // A 组件
      { this.props.render(内部state数据) }
      // C 组件 --- 读取A组件传入的数据显示
      { this.props.data }
      
      

Error boundary

错误边界(Error boundary):用来捕获后代组件错误,渲染出备用页面

只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误和其他组件在合成事件、定时器中产生的错误

使用方式

static getDerivedStateFromError(error){
  console.log(error)
  return {
    hasError: true
  }
}

componentDidCatch(error, info) {
  // 统计页面的错误,发送请求到服务端
  console.log(error, info)
}

相关文章

  • react拓展

    setState() setState更新状态的2种方式 对象式的setState 函数式的setState 对象...

  • 拓展4 (React)

    以下读http://www.ruanyifeng.com/blog/2015/03/react.html 笔记 J...

  • 拓展 (React 4)

    React-redux 产生原因: 一个状态可能被多个组件依赖或者影响,兼顾组件之间共享状态问题和共享状态可能被任...

  • 拓展(React 2)

    为什么不直接从 JSX 直接渲染构造 DOM 结构,而是要经过中间这么一层呢? 第一个原因是,当我们拿到一个表示 ...

  • 拓展 React3

    一、高阶组件(Higher-Order Components) 高阶组件就是一个函数,传给它一个组件,它返回一个新...

  • react JSX语法

    jsx语法 概念:react定义的一种类似于xml的js拓展语法 作用:用来创建react的虚拟DOM对象的var...

  • react 学习笔记 使用 jsx 语法

    react 学习笔记 使用 jsx 语法 概念 JSX 是一种 JavaScript 的语法拓展。我们推荐 rea...

  • React Navigation BottomTab 拓展版

    默认支持了 badge 角标功能,移除了原版的 tabBarOptions 属性,将 tabBarOptions ...

  • React拓展4-Fragment

    Fragment 组件能够在不额外创建 DOM 元素的情况下,让 render() 方法中返回多个元素。 一个常见...

  • React拓展5-Context

    Context:一种组件间通信方式, 常用于【祖组件】与【后代组件】间通信 Context 通过组件树提供了一个传...

网友评论

      本文标题:react拓展

      本文链接:https://www.haomeiwen.com/subject/bcaacrtx.html