我有一个具有2000个元素的React组件,并根据一些过滤条件更新我的状态,这会在内部导致重新渲染。一切似乎都很好。但是当我将2000个元素的togglefilter改为1000个元素并且返回& out时,渲染需要花费很多时间,有时浏览器会冻结。我做了镀铬时间线分析,主要耗时的部分是渲染。任何帮助将不胜感激。
答案 0 :(得分:1)
快速解决方法是实现shouldComponentUpdate
See the docs,以便渲染〜2000次子组件。
shouldComponentUpdate: function(nextProps, nextState) {
return this.props.value !== nextProps.value;
}
另一个快速检查是问你自己是否遵循使用小型无国籍儿童的惯例,只传递道具。如果没有,可能是重构的时候了。
答案 1 :(得分:1)
@enjoylife的建议是迈出的重要一步,但是如果视图中有许多组件结构,那将很难调试,即使记住该组件也无法消除连续渲染或循环渲染。
我在遇到奇怪的冻结和奇怪的错误后才学会了这一点,无论何时用户登录首页都无法停止。想象所有屏幕。有时,您几乎不会注意到组件在重新发送。
const Home = () => {
conso.log('home re-rending')
// some hooks
return <BigComponent />
}
如上所述。日志显示的时间不得超过安装组件后的限定时间。就我而言,只有一次。但是,如果太多(日志),肯定会冻结您的PC。因此,请仔细按照以下步骤操作,并追溯到您的步骤。
cra
复制了源代码,然后整理出遇到的第一个和最后一个问题。尤其要小心使用useEffect
之类的React钩子。避免在组件中造成副作用。
就我而言,我创建了一个可重用的useUpdateEffect hook
,我打算解决这个问题的名称就是检测React道具或窗口道具的更新,但事与愿违,我不会共享代码。>
另外,请检查是否传递了正确的预期期望的依赖关系,对此Eslint值得赞扬。
避免在React列表中使用随机密钥。在组件列表中使用唯一键和常数键,因为依赖于它来标识每个项目。根据{{3}}
键可帮助React识别哪些项目已更改,添加或删除。应该为数组内的元素提供键,以赋予元素稳定的身份。您可以将项目索引用作最后的选择:
避免在reducer和React组件中发生变量名冲突。请考虑使用样式指南作为您的朋友,以避免这种情况。
我犯了一个愚蠢的错误,即创建Foo类并在其render函数中使用它,这也导致了死机。在这里写下所有可能再次遇到此问题的人。react library。
避免无限循环,想象一下一次渲染很多数据。 follow this thread
this happen,我敦促您检查循环,确保没有+ =而不是-=(反之亦然)。那些无限循环可能会给脖子带来很大的痛苦。
保持您的减速器为减速器,避免操作创建者,减速器中的API调用或using another reducer in your reducer
,例如reducerA
中的reducerB
。当您调用reducerA
中的更新reducerB
时,reducerA
中的更新将触发reducerB
中的更新,从而导致页面/屏幕多次重新呈现。例如
// this react reducer in my case
// reducer js file - reducerB
const useBusinesses = () => {
// reducerB as discussed above - the loading context
const { loading } = useLoadingContext(); // the culprit
const [data, setData] = useState(initialState); // initial state,
const [state, dispatch] = useReducer(reducer, data);
useEffect(() => setData(state), [state, setData]);
const { businesses, errorMessage } = state;
const setBusinesses = (payload) => dispatch({ type: `${FETCH_BUSINESSES}_SUCCESS`, data: payload });
const setBusinessesError = (payload) => dispatch({ type: `${FETCH_BUSINESSES}_ERROR`, data: payload });
const fetchBusinesses = async (lglt, type = 'food', limit = 12) => {
try {
// update reducerB: triggers multiple update in reducerA while requesting is pending
loading(FETCH_BUSINESSES, true);
const request = await API.businesses.getWithquery(
`long=${lglt[0]}&latt=${lglt[1]}&limit=${limit}&type=${type}`
);
loading(FETCH_BUSINESSES, false);
setBusinesses(request.data);
} catch (err) {
loading(FETCH_BUSINESSES, false);
// if (!err.response) dispatch(alertMessage(FETCH_BUKKAS, true, 'Please check your network'));
setBusinessesError(err.response.data);
}
});
return { businesses, errorMessage, fetchBusinesses };
};
export const [BusinessesProvider, useBusinessesContext] = constate(useBusinesses);
//home js file
Home = () => {
const { fetchBusinesses } = useBusinessContext();
conso.log('home re-rending')
// some hooks
useEffect(() => {
console.log('am i in trouble, yes!, how many troubles')
fetchBusinesses(coordinates)
}, [fetchBusinesses, coordinates])
return <BigComponent />
}