Reaccionar las deficiencias de PureComponent en la entrega de accesorios funcionales

1. Surge el problema

Con el fin de mejorar la eficiencia en el proyecto, se utilizó una gran cantidad de PureComponents en lugar del Componente original para evitar volver a renderizar con componentes y para impulsar la repetición de todos los nodos secundarios. Para PureComponent, sabemos claramente que solo se basa en el Componente original, a través de una comparación superficial shallowEqual, para proporcionarnos una capa de juicio shouldComponentUpdate. Para evitar que llamemos repetidamente a la función render cuando los accesorios y el estado permanecen sin cambios, lo que resulta en una degradación del rendimiento. La mayoría de las mejoras son suaves, solo es necesario extraer la transferencia de accesorios poco profundos. Pero para transferencias de accesorios funcionales, como la siguiente escritura, la referencia pasada cambiará cada vez, y shallowEqual se juzgará como falso al juzgar, lo que llevará al abandono de los esfuerzos anteriores.

//--ParentComponent
render()
{
    
    
	return <ChildComponent onCallback={
    
    ()=>{
    
    //--do something}} />
}

o

//--ParentComponent
render()
{
    
    
	return <ChildComponent onCallback={
    
    this.doSomeThing.bind(this)}/>
}

Los dos anteriores se pueden resolver vinculando esto en el constructor o usando funciones de flecha para mejorar el alcance:

//--ParentComponent
onCallback = () =>{
    
    
	//--do something
}
render()
{
    
    
	return <ChildComponent onCallback={
    
    this.onCallback } />
}

o

constructor()
{
    
    
	this.onCallback = this.onCallback.bind(this);
}
onCallback(){
    
    
	//--do something
}
render()
{
    
    
	return <ChildComponent onCallback={
    
    this.onCallback } />
}

Pero cuando ocurre la siguiente situación, es decir, mi devolución de llamada debe depender de algunos datos de la capa superior para su procesamiento cuando se activa. ¿Piensa cómo lidiar con eso sin usar funciones de cierre?

doSomeThingWith(dependence){
    
    
    //--use dependence to do something
}
render()
{
    
    
    const someAnycMethods = (dependence) => {
    
    
        return <ChildComponent onCallback = {
    
    ()=>{
    
    this.doSomeThingWith(dependence)}}/>
    }
}

2. Resolución de problemas

No hablemos de los problemas anteriores. En general, podemos mantener pureComponent nosotros mismos para evitar las dos situaciones anteriores, pero es posible que otros colegas no conozcan sus reglas. Pueden pasar accidentalmente una función de flecha de cierre o usar bind, destruyendo pureComponent. Teniendo en cuenta que casi no hay diferencia en la función de transferencia en el proyecto que afectará la representación de dom en el subcomponente , por ejemplo, el patrón de diseño de renderProps no es aplicable. Entonces, si asumimos que la diferencia en la función de devolución de llamada pasada no afectará el resultado de la representación , ¿podemos ignorar los accesorios del tipo de función?

código fuente shallowEqual:

function is(x, y) {
    
    
    if (x === y) {
    
    
        return x !== 0 || y !== 0 || 1 / x === 1 / y;
    } else {
    
    
        return  x !== x && y !== y;
    }
}

const shallowEqual = (objA, objB) => {
    
    
    if (is(objA, objB)) {
    
    
        return true;
    }
    if (
        typeof objA !== 'object' ||
        objA === null ||
        typeof objB !== 'object' ||
        objB === null
    ) {
    
    
        return false;
    }

    const keysA = Object.keys(objA);
    const keysB = Object.keys(objB);

    if (keysA.length !== keysB.length) {
    
    
        return false;
    }
    for (let i = 0; i < keysA.length; i++) {
    
    
        if (
            !hasOwnProperty.call(objB, keysA[i]) ||
            !is(objA[keysA[i]], objB[keysA[i]])
        ) {
    
    
            return false;
        }
    }

    return true;
}

export default shallowEqual;

Mi enfoque aquí es modificar la lógica de juicio shallowEqual en la que se basa shouldCompoentUpdate, y agregar excepciones de accesorios funcionales:

function is(x, y) {
    
    
    if (x === y) {
    
    
        return x !== 0 || y !== 0 || 1 / x === 1 / y;
    } else {
    
    
    	//--添加函数式props例外
		if(typeof x === 'function' && typeof y === 'function')
		   return true;
	    return  x !== x && y !== y;
    }
}

Finalmente, envuelva un UnsafePureComponent de la siguiente manera

import {
    
     Component } from 'react';
import shallowEqual  from '../util/shallow-equal-pached'
export default class UnsafePureComponent extends Component {
    
    

    shouldComponentUpdate(nextProps, nextState) {
    
    
        return !shallowEqual(this.props, nextProps) || !shallowEqual(this.state, nextState);
    }
}

El componente se puede heredar directamente del proyecto. Esto no solo evita la falla en el renderizado de interceptación causado por el mal funcionamiento de otros colegas, sino que también resuelve el problema del renderizado causado por diferentes referencias de parámetros funcionales.

Supongo que te gusta

Origin blog.csdn.net/qq_29722281/article/details/107889997
Recomendado
Clasificación