美文网首页
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拓展

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