Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/428.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 反应-作为道具使用,产生额外的渲染效果_Javascript_Reactjs - Fatal编程技术网

Javascript 反应-作为道具使用,产生额外的渲染效果

Javascript 反应-作为道具使用,产生额外的渲染效果,javascript,reactjs,Javascript,Reactjs,我正在处理一些重的表格。因此,我在尽可能地压缩性能。最近,我添加了Why Doy you render插件,以便更深入地了解哪些因素可能会降低我的页面速度。例如,我注意到,当我单击复选框组件时,所有其他组件都会重新渲染。理由总是一样的。WDYR说 由于道具更改而重新渲染:使用 同名{prev onChangeHandler:ƒ}”!==“{下一个onChangeHandler:ƒ}” 我尽可能地尊重我发现的最佳实践指示。我的组件传递的回调函数遵循以下模式 import React, { useS

我正在处理一些重的表格。因此,我在尽可能地压缩性能。最近,我添加了Why Doy you render插件,以便更深入地了解哪些因素可能会降低我的页面速度。例如,我注意到,当我单击复选框组件时,所有其他组件都会重新渲染。理由总是一样的。WDYR说

由于道具更改而重新渲染:使用 同名{prev onChangeHandler:ƒ}”!==“{下一个onChangeHandler:ƒ}”

我尽可能地尊重我发现的最佳实践指示。我的组件传递的回调函数遵循以下模式

import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
export function TopLevelComponent({props}){

    const defaultData = {name: '', useMale: false, useFemale: false}

    const [data, setData] = useState(defData);
    const { t } = useTranslation();
    const updateState = (_attr, _val) => {
        const update = {};
        update[_attr] = _val;
        setData({ ...data, ...update });
    }

    const updateName = (_v) => updateState('name', _v);//Text input
    const updateUseMale = (_v) => updateState('useMale', _v);//checkbox
    const updateUseFemale = (_v) => updateState('useFemale', _v);//checkbox
    ...

    return <div>
        ...
        <SomeInputComponent value={data.name} text={t('fullName')} onChangeHandler={updateName} />
        <SomeCheckboxComponent value={data.useMale} onChangeHandler={updateUseMale} text={t('useMale')}/>
        <SomeCheckboxComponent value={data.useFemale} onChangeHandler={updateUseFemale} text={t('useFemale')}/>
        ...
    </div>
}

import React,{useState,useffect}来自“React”;
从“react-i18next”导入{useTranslation};
导出函数TopLevelComponent({props}){
const defaultData={name:'',UseMeal:false,UseMeal:false}
const[data,setData]=使用状态(defData);
const{t}=useTranslation();
const updateState=(\u attr,\u val)=>{
常量更新={};
更新[\u attr]=\u val;
setData({…数据,…更新});
}
const updateName=(_v)=>updateState('name',_v);//文本输入
const updateUseMale=(\u v)=>updateState('useMean',\u v);//复选框
const updateUseFemale=(\u v)=>updateEstate('useFemale',\u v);//复选框
...
返回
...
...
}
在这样的示例中,更改任何输入(例如:在文本输入中写入文本或单击其中一个复选框)都会导致其他2个组件按照上面给出的对齐方式重新渲染


我想我可以停止使用功能组件,使用
shouldComponentUpdate()
函数,但功能组件确实提供了一些我宁愿保留的优势。我应该如何编写函数,使与一个输入交互时不会强制更新另一个输入?

问题源于您定义更改处理程序的方式:

const updateName = (_v) => updateState('name', _v)
在每次渲染时都会调用这一行,因此,每次渲染组件时,道具都会有一个新的(尽管功能上完全相同)值。其他处理程序也是如此


作为一个简单的解决方案,您可以将功能组件升级为成熟的组件,并在渲染功能之外缓存处理程序,也可以在子组件中实现。

您需要对子组件使用
memo
来减少渲染

const SomeInputComponent=props=>{
};
导出默认备忘录(SomeInputComponent);
//如果它仍然导致重新渲染而不改变任何道具,则可以使用回调来允许或阻止渲染
e、 f。
功能arePropsEqual(前一个Props,下一个Props){
return prevProps.name===nextProps.name;//使用您的逻辑来确定props是否相同
}
导出默认备忘(SomeInputComponent,arePropsEqual);
/*重新渲染的一个原因是,传递给子组件的“onChange”回调在每个父级渲染上都是新的,这会导致子组件重新渲染,即使您使用“momo”,因为函数在每个渲染上都会更新,所以为了修复此问题,您可以使用React hook“useCallback”在每个渲染上获得相同的函数引用。
因此,在父组件中,需要执行以下操作
*/
从“react”导入{useCallback};

const updateName=useCallback((_v)=>UpdateEstate('name',_v),[])
在传递给子函数之前,必须先记住父函数,对函数组件使用useCallback,如果使用class,则转换为class属性

export default class Parent extends React.PureComponent {
    constructor(props) {
       super(props);
       this.onClick = this.onClick.bind(this);
    }

    onClick() {
       console.log("click");
    }

    render() {
        return (
           <ChildComponent
               onClick={ this.onClick }
           />
        );
    }
}
导出默认类父级扩展React.PureComponent{
建造师(道具){
超级(道具);
this.onClick=this.onClick.bind(this);
}
onClick(){
控制台日志(“单击”);
}
render(){
返回(
);
}
}
使用useCallback:

Parent = () => {
   const onClick = useCallback(
      () => console.log('click'),
      [] 
   );

   return (
        <ChildComponent
            onClick={onClick}
        />
   );
}
Parent=()=>{
const onClick=useCallback(
()=>console.log('click'),
[] 
);
返回(
);
}

您能再添加一点代码让我们理解吗。我们有
memo
usemo
等工具来减少不必要的成本renders@ZohaibIjaz您想要组件特定的函数吗?实际上,我不知道是哪个组件导致了更改,哪些组件得到了渲染,而这些组件不需要渲染。@ZohaibIjaz添加了更多的代码。我试着使用
memo
,但对于需要更复杂数据的组件,我得到了一些奇怪的结果。如果这是解决方案,我将尝试使用memo调试代码。您是否使用上下文作为状态?您的状态驻留在哪里?当传递给子组件的值是对象时,您将如何使用memo?对于某些组件,我有一些复杂的数据对象,我尝试了类似
memo(MyComponent,(\u prev,\u next)=>JSON.stringify(\u prev.values)===JSON.stringify(\u next.values))但这似乎不起作用。我需要逐个属性进行比较吗?@Axel查看关于使用
useCallback
的更新答案。我希望它能解决您的问题,您不需要在
memo()
中传递额外的
arePropsSame
回调,我尝试使用
useCallback
将我的所有回调看起来像
const updateFnc=useCallback((_v)=>updateState('someAttr',u v),[])
但这只更改了WDYR:Re-rendered的错误代码,因为props对象本身已更改,但其值都相等。单击复选框后,文本输入中会出现该错误