react16.8新特性

2020-02-22  本文已影响0人  b59a2ae26f20

1 => 16.8 的context主要的目的是为跨越多个层级的组件提供数据的共享

import React, {Component, createContext} from 'react';
import logo from './logo.svg';
import './App.css';
const CountNumContext = createContext()
const CountStateContext = createContext()

class DetailPart extends Component{
  render() {
    return (
      <CountNumContext.Consumer>
        {
          countNum =>
          {
            return (
              <CountStateContext.Consumer>
                {
                  countState => <h1>countNum: {countNum}, countState: {String(countState)}</h1>
                }
              </CountStateContext.Consumer>
            )

          }
        }
      </CountNumContext.Consumer>

    )
  }
}

class ChildPart extends Component{
  render() {
    return (
      <DetailPart/>
    )
  }
}
class App extends Component {
  state = {
    countNum: 1,
    countState: false
  }
  render() {
    const {countNum, countState} = this.state
    return (
      <CountNumContext.Provider value={countNum}>
        <CountStateContext.Provider value={countState}>
          <button onClick={() => {this.setState({countNum: countNum + 1 })}}>addNum</button>
          <button onClick={() => {this.setState({countState: !countState})}}>switchState</button>
          <ChildPart></ChildPart>
        </CountStateContext.Provider>
      </CountNumContext.Provider>
    )
  }


}

export default App;

以上写法也可以通过contextType的方式省略consumer

import React, {Component, createContext} from 'react';
const CountContext = createContext()

class DetailPart extends Component{
  static contextType = CountContext
  render() {
    const count = this.context
    return (
      <h1>countNum: {count.countNum}, countState: {String(count.countState)}</h1>
    )
  }
}

class ChildPart extends Component{
  render() {
    return (
      <DetailPart/>
    )
  }
}

class App extends Component {
  state = {
    countNum: 1,
    countState: false
  }
  render() {
    const {countNum, countState} = this.state
    return (
      <CountContext.Provider value={this.state}>
          <button onClick={() => {this.setState({countNum: countNum + 1 })}}>addNum</button>
          <button onClick={() => {this.setState({countState: !countState})}}>switchState</button>
          <ChildPart></ChildPart>
      </CountContext.Provider>
    )
  }
}

export default App;

2 => lazy和Suspense配合优化性能

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

const TestLazy = lazy(() => import(/* webpackChunkName: "testLazy" */'./components/TestLazy.jsx'))

class App extends Component {

  render() {
    return (
      <div>
        <Suspense fallback={<div>loading</div>}>
          <TestLazy/>
        </Suspense>
      </div>
    )
  }
}

export default App;

3 memo => 类组件的PureComponent相比component,区别在于shouldComponentUpdate, 前者等于自己封进行了装装,但无法识别对象中的对象。而memo则是赋予函数组件相同的PureComponent

const Foo = memo(function Foo(props) {
  return (
    <div>{props.person.age}</div>
  )
})

4 useEffect=> useEffect(() => {} , []) , useEffect的执行时机主要取决于第二个参数。(无论哪种情况,初始都会执行一遍)
情况 1,如果没有第二个参数,则每次改变当前函数的state,和初始执行,都会接受回调
情况 2,如果第二个参数传入的数组变量是state中定义的某个变量,则会当改变这个变量的时候,执行传入useEffect的第一个函数
情况 3,如果第二个参数是空数组,则在初始执行useEffect传入的第1个函数。在销毁组件时执行useEffect第一个参数返回的函数

import React, {useEffect, useState} from 'react';

function App() {
  const [count, setCount] = useState(0)
  const [size, setSize] = useState({
    width: document.documentElement.clientWidth,
    height: document.documentElement.clientHeight
  })

  const onResize = () => {
    setSize({
      width: document.documentElement.clientWidth,
      height: document.documentElement.clientHeight
    })
  }
  useEffect(() => {
    console.log('--情况1--')
  })
  useEffect(() => {
    console.log('--情况2--')
    //当count改变时执行
    console.log('count:', count)
  }, ['count'])

  useEffect(() => {
    console.log('--情况3--')
    //组件初始执行
    window.addEventListener('resize', onResize, false)
    return () => {
      //组件结束执行
      window.removeEventListener('resize', onResize, false)
    }
  }, [])

  return  (
    <div>
      <button onClick={() => setCount(count+1)}>{count}</button>
      <p>width: {size.width}, Height: {size.height}</p>
    </div>
  )
}

export default App;

5 useMemo,useCallback => 这两个函数大同小异,用法类似都可以作为回调函数传递给子组件

import React, {memo, useState, useMemo, useCallback} from 'react';

const Counter = memo(function (props) {
  console.log('--momoCounterRendered--')
  return (
    <div onClick={props.onClick}>consoleCount</div>
  )
})

function App() {
  const [count, setCount] = useState(0)
  const onClick1 = useMemo(() => {
    return () => (
      console.log('fetching:'+ count)
    )
  },[])
  const onClick = useCallback(() => {
    console.log(count)
    setCount((count) => {
      return count + 1
    })
  }, [count])
  return  (
    <div>
      <button onClick={() => {setCount(count + 1)}}>addCount{count}</button>
      <Counter onClick={onClick}/>
    </div>
  )
}

export default App;

6 useRef => useRef 可以用来在父组件中获取子组件的句柄或调用dom属性

import React, {PureComponent, useState, useRef, useCallback} from 'react';

class Counter extends PureComponent{
  init() {
    console.log('---init---')
  }

  render() {
    const {props} = this
    return (
      <div onClick={props.onClick}>consoleCount:{props.count}</div>
    )
  }
}

function App() {
  const [count, setCount] = useState(0)

  const CounterRef = useRef()

  const onClick = useCallback(() => {
    CounterRef.current.init()
  }, [CounterRef])
  return  (
    <div>
      <button onClick={() => {setCount(count + 1)}}>addCount{count}</button>
      <Counter count={count} ref={CounterRef} onClick={onClick}/>
    </div>
  )
}

export default App;
上一篇下一篇

猜你喜欢

热点阅读