React - 高级用法

React高级用法

Hooks

Reducer

useReducer:

js 复制代码
import React, { useReducer, useState } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
    switch (action.type) {
        case 'increment':
            return { count: state.count + 1 }
        case 'decrement':
            return { count: state.count - 1 }
        default:
            console.log('格式不通过!');
    }
}

export default function Reducer() {
    const [number, setNumber] = useState(0);
    
    const [state, dispatch] = useReducer(reducer, initalState);
    
    return (
        <div>
            {state.count}
            <button onClick={() => dispatch({ type: 'increment' })}>+</button>
        </div>
    )
}

Ref

用来指代具体的dom节点

类组件: createRef

js 复制代码
import React, { Component } from 'react';

export default class ClassRef extends Component {
    
    constructor(props) {
        super(props);
        
        this.eleRef = createRef();
        this.inputRef = createRef();
    }
    
    handleClick = () => {
        this.inputRef.current.focus();
        console.log(this.eleRef.current);
    }
    
    render() {
        return (
            <div>
                <div id="xxx" ref={this.eleRef}> eleRef </div>
                <input ref={this.inputRef} />
                
                <button onClick={this.handleClick}></button>
            </div>
        )
    }
    
}

函数组件:useRef

js 复制代码
import { useRef } from 'react'

export default function FuncRef(props) {
    
    const eleRef = useRef(null);
    const inputRef = useRef(null);
    
    return (
        <div>
            <div id="xxx" ref={this.eleRef}> eleRef </div>
            <input ref={this.inputRef} />
            
            <button onClick={this.handleClick}></button>
        </div>
    )
    
}

Ref转发

类似于vue中 调用子组件的方法 refs.xxx()

Context上下文

Provider

Comsumer

对应Vue,就是provide,inject

形成一个生成与消费模式的上下文

类组件用法

js 复制代码
import { createContext } from 'react';

const ThemeContext = createContext('light');

//    ClassContext.jsx
export default class ClassContext extends Component {
    
    constructor(props) {
        super(props);
        this.state = {
             theme: 'light'
        }
    }

    render() {
        return (
            <div>
                <ThemeContext.Provider
                    value={this.state.theme}
                >
                    <Parent />
                    <button onClick={() => this.setState({ theme: 'light' })}></button>
                </ThemeContext.Provider>
            </div>
        )
    }
}

const Parent = () => {
    return (
        <div>
            <Child1 />
            <Child2 />
        </div>
    )
}

class Child1 extends Component {

    static contextType = ThemeContext;
    render() {
        return (
            <div>
                {this.context}
            </div>
        )
    }
}

class Child2 extends Component {
    render() {
        return (
            <ThemeContext.Consumer>
                {
                    (theme) => (
                        <div>{theme}</div>
                    )
                }
            </ThemeContext.Consumer>
        )
    }
}

History包装(函数组件)

js 复制代码
import { useContext, useState, createContext } from 'react';

const ThemeContext = createContext();
const history = window.history;

export default function FuncContext() {
    return (
        <ThemeContext.Provider value={history}>
            <Parent />
        </ThemeContext.Provider>
    )
}

const Parent = () => {
    return <Child />;
}

const withRouter = (Component) => {
    console.log(Component, 'ComponentComponent')
    return () => {
        const nav = useContext(ThemeContext);
        return <Component navigator={nav} />
    }
}

const Child = withRouter((props) => {
    console.log(props);
    return (
        <div>
            <button onClick={() => props.navigator.pushState({}, undefined, 'hello')}>
                hello
            </button>
        </div>
    )
})

高阶函数(HOC)

函数可以作为 参数 和 返回值 。

属性代理

js 复制代码
//    CardHoc.jsx
export default function Card({ title, children }) {
    return <div>
        <h2>{ title }</h2>
        {
            children ? 
            <div>{ children }</div> : null
        }    </div>
}

export const withCard = (title) => (Component) => {
    return (props) => {
        const hocStyle = {
            margin: '12px',
            padding: '12px',
            border: '1px solid #ccc',
            borderRadius: '4px'
        }
    
        return <div style={hocStyle}>
            <h2>{title}</h2>
            <Component {....props} />
        </div>
    }
}

//    App.jsx
const Text = ({ num }) => <div>{num}</div>
const CardText = withCard('TextCard')(Text);
<CardText num={100} />

反向继承

js 复制代码
import { Component } from 'react';

//    比如我们有一个案例: 我们需要优雅的实现 曝光埋点
/**
 * 有个按钮,我们想知道这个按钮在线上的漏斗转换
 * 每次按钮点击时,记录一个sendLog('my_btn_click'), 其实就是触发一条请求
 * 每次按钮出现时,记录一个sendLog('my_btn_show')
 * 那我的转化,pv('my_btn_click') / pv('my_btn_show')
 */

export default function Extending() {
    return (
        <div><LogIndex /></div>
    )
}

function logProps(logMap) {
    return (WrapperComponent) => {
        const didMount = WrapperComponent.prototype.componentDidMount;
        return class A extends WrapperComponent {
            componentDidMount() {
                if (didMount) {
                    didMount.apply(this);
                }
                
                Object.entries(logMap).forEach([k, v] => {
                    if (document.getElementById(k)) {
                        console.log('事件曝光', v);
                    }
                })
            }
            
            render() {
                return super.render();
            }
        }
    }
}
class Index extends Component {
    render() {
        <div>
            <div id="my_text">这是一个文字信息</div>
            <button id="my_btn">这是一个按钮</button>
        </div>
    }
}

const LogIndex = logProps({
    my_text: 'my_text_show',
    my_btn: 'my_btn_show'
})(Index)

渲染优化

类组件 类似于useMemo

js 复制代码
import React, { Component } from 'react'
export default class renderControl extends Compoent {
    
    constructor(props) {
        super(props);
        this.state = {
            num: 0,
            count: 0
        }
        
        this.component = <Child num={this.state.num}>
    }
    
    controlRender = () => {
        const { props } = this.component;
        if (props.num !== this.state.num) {
            return this.component = React.cloneElement(
                this.component,
                { num: this.state.num }
            )
        }
    }
    
    render() {
        
        const { num, count } = this.state;
        
        return <div>
            {this.controlRender()}
            <button onClick={() => this.setState({ num: num + 1 })}>{num}</button>    
            <button onClick={() => this.setState({ count: count + 1 })}>{count}</button>    
        </div>
    }
}

const Child = ({ num }) => {
    console.log('子组件执行');
    return <div>{ num }</div>
}

函数组件 - useMemo

js 复制代码
import React, { Component, useState } from 'react'
export default function renderControl() {
    
    const [ num, setNum ] = useState(0);
    const [ count, setCount ] = useState(0);
    
    return <div>
            {useMemo(() => <Child num={num} />, [num])}
            <button onClick={() => this.setState({ num: num + 1 })}>{num}</button>    
            <button onClick={() => this.setState({ count: count + 1 })}>{count}</button>    
        </div>

    
}

const Child = ({ num }) => {
    console.log('子组件执行');
    return <div>{ num }</div>
}

useMemo

函数:返回值进行缓存;

Deps: 依赖项改变了,我就再次执行;

useCallback

函数:函数进行缓存

Deps: 依赖项改变了,我就再次执行;

js 复制代码
import React, { useCallback, useState } from 'react';

export default function RenderControl() {
    
    const [num, setNum] = useState(0);
    const [count, setCount] = useState(0);
    
    const handleChange = useCallback(() => {
        setCount(count => count + 1);
    }, [])
    
    return (
        <div>
            <MemoChild onChange={handleChange} />
            <button onClick={() => setNum(num + 1)}>{num}</button>
            <button onClick={() => setCount(count + 1)}>{count}</button>
        </div>
    )
}

const Child = ({ num, onChange }) => {
    console.log('子组件执行');
    return <div>
        <button onClick={() => onChange()}>
            onChange
        </button>
    </div>
}

const MemoChild = React.memo(Child);
相关推荐
逐·風15 分钟前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
Devil枫44 分钟前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
尚梦1 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
GIS程序媛—椰子2 小时前
【Vue 全家桶】6、vue-router 路由(更新中)
前端·vue.js
前端青山2 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
毕业设计制作和分享3 小时前
ssm《数据库系统原理》课程平台的设计与实现+vue
前端·数据库·vue.js·oracle·mybatis
从兄3 小时前
vue 使用docx-preview 预览替换文档内的特定变量
javascript·vue.js·ecmascript
清灵xmf4 小时前
在 Vue 中实现与优化轮询技术
前端·javascript·vue·轮询
大佩梨5 小时前
VUE+Vite之环境文件配置及使用环境变量
前端
GDAL5 小时前
npm入门教程1:npm简介
前端·npm·node.js