react复习总结

645 阅读2分钟

react

1.依赖上次更新的更新

 this.setState(prevState => {
           return {
               count: prevState.count + 1
           }
       })

2.b避免重复更新

1.原始写法

shouldComponentUpdate(nextProps){
        if(nextProps.data.body === this.props.data.body){
            return false
        }else{
            return true
        }
    }

2.15.3后 浅比较(值类型有效)

class Comment extends PureComponent{

}

3.16.6后React.memo来完美实现react组件,让函数式组件也有PureComponent的功能

const Comment = React.memo(
    function (props){
        return (
            <div>
                <p>{props.body}</p>
            </div>
        )
    }
)
//接收一个组件,返回一个全新的组件

3.高阶组件(本身为函数)

//接收一个组件,返回一个新组件(解决组件的复用)

//展示性组件
function Indexs(props){
    return(
        <div>
            {props.stage} - {props.name}
        </div>
    )
}
//高阶组件
const Home = Comp =>{
    //获取name
    const name = '高阶组件'
    return props => (
        <Comp {...props} name={name}></Comp>
    )
}

//使用
const NewHome = Home(Indexs)

export default class Hoc extends Component{
    render(){
        return(
            <div>
                <NewHome stage='React' />
            </div>
        )
    }
}

可以改变生命周期的高阶组件

const MyHome = Comp =>{
    //获取name
    const name = '高阶组件'
    return class extends Component(
        conponentDidMount(){
            console.log('这是带生命周期的高阶组件')
        }
        render(){
          return  <Comp {...this.props} name={name}></Comp>
        }
    )
}

高阶组件可以链式调用 const NewHome = Home(MyHome(Indexs))


4.装饰器(ES7)

1.依赖

npm install babel-plugin-transform-decorators-legacy -S

//配置
config.overnides.js
config = injectBabelPlugin(
    config = injectBabelPlugin(
        ['@babel/plugin-proposal-decorators',{ legacy : true}],
        config
    )
    return config;
)

2.使用

//装饰器 只能应于class组件

//注意 MyHome ,  Indexs 高阶组件要写作展示性组件上面

@MyHome
@Indexs
//展示性组件
class Indexs extends Component {
    render(){
        return (
            <div>
                {this.props} - {this.props.name}
            </div>
        )
    }
}
//直接使用 Indexs 即可为高阶组件

5.组件复合

//Dialong 作为容器,不关心内容喝逻辑
function Dialog(props){
    retrun <div style={{border: `1px solid ${props.color || 'red'}`}}>{props.children}</div>
}

//WelcomeDialog 通过复合提供内容
function WelcomeDialog(props){
    return (
        <Dialog {...props}>
            <h1>欢迎光临</h1>
        </Dialog>
    )
}

//等同于vue的slot
//react 推荐写法

export default function(){
    return <WelcomeDialog color= 'red'/>
}

children实际为任何JS

const APi = {
    getUser(){
        return { name : 'jerry' , age : 20}
    }
}
function Fetch(props){
    const user = APi[props.name]();
    return props.childern(user)
}
export default function(){
    return (
        <Fetch name= 'getUser'>
        {({name,age})=>{
            <p>
              {name} - {age}  
            </p>
        }}
        </Fetch>
    )
}

过滤


function Fetch({children,type}){
 
    return(
        <div>
            {React.Children.map(children,child =>{
                if(child.typr !== type){
                    return;
                }
                retrun child
            })}
        </div>
    )
}
//只显示p标签
export default function(){
    return (
        <Fetch type='p'>
            <h1>react</h1>
            <h2>react很不错呀</h1>
            <h3>哈哈</h3>
            <p>这是p</p>
        </Fetch>
    )
}

克隆

function RadioGroup(props){
    return (
        <div>
            {React.Children.map(props.children,child =>{
                // vdom 不可更改,需要克隆一个新的 才能去改
              return  React.cloneElement(child, {name: props.name})
            }) }
        </div>
    )
}

function Radio({children,..rest}){
    return (
        <label>
            <input type='radio' {...rest} />
            {children}
        </label>
    )
}

export default function(){
    return (
       <RadioGroup name='mvvm'>
            <Radio value='vue'>vue</Radio>
            <Radio value='react'>react</Radio>
       </RadioGroup>
    )
}

6.Hook

1.单状态

import React,{ useState } from 'react'

export default function HookTest(){

    const [count,setCount] = useState(0)

    return (
        <div>
            <p>点击了{count}
            <button onClick={() => setCount(count+1)}>点击了</button>
        </div>
    )
}

//使用
<HookTest></HookTest>

2.多状态

import React,{ useState } from 'react'

export default function HookTest(){

    const [count,setCount] = useState(0)
    const [age,setAge] = useState(20)
    const [all,setAll] = useState([1,2,3])

    return (
        <div>
            <p>点击了{count}
            <button onClick={() => setCount(count+1)}>点击了</button>
        </div>
    )
}

//使用
<HookTest></HookTest>

7.副作用钩子 Effect Hook

import React,{ useState } from 'react'

export default function HookTest(){

    const [count,setCount] = useState(0)
    const [age,setAge] = useState(20)
    const [all,setAll] = useState([1,2,3])

    //副作用钩子会在每次渲染时都执行
    /**
     * 相当于componentDidMount,componentDidUpdate,componentUnmount
     * 的一个综合体,可以拥有多个
    */
   // 1. 只要业务发生变化就会执行
    useEffect(()=>{
        document.title = `你点击了${count}次 `
    })

    /**
     * 如果今打算执行一次,可在第二个参数传入一个空数组
     *     
    */
    // 2.只会在挂载是时候执行一次
     useEffect(()=>{
        document.title = `你点击了${count}次 `
    },[])

    // 3.只有count 发生变化了 才会执行
     useEffect(()=>{
        document.title = `你点击了${count}次 `
    },[count])

    return (
        <div>
            <p>点击了{count}
            <button onClick={() => setCount(count+1)}>点击了</button>
        </div>
    )
}

//使用
<HookTest></HookTest>

8.自定义钩子

自定义钩子 是一个函数

function sueAge(){
    const [ age, setAge ] = useState(0)
    useEffect(() => {
        setTimeout(() =>{
            setAge(20)
        },2000)
    })

    return age
}


import React,{ useState } from 'react'

export default function HookTest(){

    const count= sueAge()

    return (
        <div>
            <p>点击了{count}</p>
        </div>
    )
}

9.其他Hook

useContext,useReducer,useCallback,useMemo


10.上下文

隔代组件传值

import React from 'react'

//创建上下文
const MyConText = React.createContext()
const { Provider , Consumer} = MyConText

function Child(prop){
    return (
        <div>
            Child :{prop.foo}
        </div>
    )
}

export default function ContextTest(){
    return (
        <div>
            <Provider value={{foo: 'bar'}}>
                <Consumer>
                    {value => <Child {...value}></Child>}
                </Consumer>
                
            </Provider>
        </div>
    )
}

2.Hook

import React,{ useContext } from 'react'

//创建上下文
const MyConText = React.createContext()
const { Provider , Consumer} = MyConText

function Child(prop){
    const ctx = useContext(MyConText)
    return (

        <div>
            Child :{ctx.foo}
        </div>
    )
}

export default function ContextTest(){
    return (
        <div>
            <Provider value={{foo: 'bar'}}>
                <Child></Child>
            </Provider>
        </div>
    )
}

3.class

import React,{ useContext } from 'react'

//创建上下文
const MyConText = React.createContext()
const { Provider , Consumer} = MyConText

class Child extends Component{
    static contextType = MyConText
    render(){
        return <div>Child : {this.context.foo}</div>
    }
}

export default function ContextTest(){
    return (
        <div>
            <Provider value={{foo: 'bar'}}>
                <Child></Child>
            </Provider>
        </div>
    )
}