如何减少调用 useEffect 的次数?
How to reduce the number of times useEffect is called?
Google 的灯塔工具给我的应用程序带来了令人震惊的性能得分,因此我一直在进行一些调查。我有一个名为 Home
的组件
里面 Home
我有 useEffect(只有一个)看起来像这样
useEffect(() => {
console.log('rendering in here?') // called 14 times...what?!
console.log(user.data, 'uvv') // called 13 times...again, What the heck?
}, [user.data])
我知道您放置了 []
的第二个参数,以确保 useEffect
仅在数据更改后才被调用,但这是我不明白的主要部分。当我控制台日志 user.data
时,前 4 个控制台日志是空数组。接下来的 9 个是长度为 9 的数组。所以在我看来,它应该只调用了两次?一次用于 []
一次用于 [].length(9)
那么到底发生了什么?
我真的需要减少它,因为它一定会影响我的表现。如果我还能做些什么来显着减少这些电话,请告诉我
我就是这样得到的user.data
const Home = ({ ui, user }) => {
// 我把它作为道具传入这里
const mapState = ({ user }) => ({
user,
})
然后我的组件已连接,所以我将其传递到这里
为了克服这种情况,React Hooks 还提供了称为 useMemo 的功能。
您可以使用 useMemo 而不是 useEffect,因为 useMemo 缓存它渲染的实例,并且每当它命中渲染时,它首先检查缓存以查看是否有任何相关实例可用于给定的 deps。如果是这样,那么而不是 运行 整个函数它将简单地return它从缓存中。
这不是答案,但代码太多,无法放入评论中。首先,您可以通过临时替换原始根减速器来记录所有更改 user.data 的操作:
let lastData = {};
const logRootReducer = (state, action) => {
const newState = rootReducer(state, action);
if (newState.user.data !== lastData) {
console.log(
'action changed data:',
action,
newState.user.data,
lastData
);
lastData = newState.user.data;
}
return newState;
};
导致 user.data 不断变化的另一件事是当你在减速器中做这样的事情时:
if (action.type === SOME_TYPE) {
return {
...state,
user: {
...state.user,
//here data is set to a new array every time
data: [],
},
};
}
相反,您可以这样做:
const EMPTY_DATA = [];
//... other code
data: EMPTY_DATA,
您的选择器正在 user
脱离状态并创建一个会导致组件重新渲染的新对象,但效果的依赖性是 user.data 因此效果只会 运行 如果数据实际改变了。
Redux devtools 也以错误的方式显示差异,如果你改变状态中的某些东西,devtools 会将它们显示为更改,但 React 不会将它们视为更改。当您将新对象分配给某物时 data:[]
然后 redux 不会将它们显示为更改但 React 会将其视为更改。
Google 的灯塔工具给我的应用程序带来了令人震惊的性能得分,因此我一直在进行一些调查。我有一个名为 Home
里面 Home
我有 useEffect(只有一个)看起来像这样
useEffect(() => {
console.log('rendering in here?') // called 14 times...what?!
console.log(user.data, 'uvv') // called 13 times...again, What the heck?
}, [user.data])
我知道您放置了 []
的第二个参数,以确保 useEffect
仅在数据更改后才被调用,但这是我不明白的主要部分。当我控制台日志 user.data
时,前 4 个控制台日志是空数组。接下来的 9 个是长度为 9 的数组。所以在我看来,它应该只调用了两次?一次用于 []
一次用于 [].length(9)
那么到底发生了什么?
我真的需要减少它,因为它一定会影响我的表现。如果我还能做些什么来显着减少这些电话,请告诉我
我就是这样得到的user.data
const Home = ({ ui, user }) => {
// 我把它作为道具传入这里
const mapState = ({ user }) => ({
user,
})
然后我的组件已连接,所以我将其传递到这里
为了克服这种情况,React Hooks 还提供了称为 useMemo 的功能。 您可以使用 useMemo 而不是 useEffect,因为 useMemo 缓存它渲染的实例,并且每当它命中渲染时,它首先检查缓存以查看是否有任何相关实例可用于给定的 deps。如果是这样,那么而不是 运行 整个函数它将简单地return它从缓存中。
这不是答案,但代码太多,无法放入评论中。首先,您可以通过临时替换原始根减速器来记录所有更改 user.data 的操作:
let lastData = {};
const logRootReducer = (state, action) => {
const newState = rootReducer(state, action);
if (newState.user.data !== lastData) {
console.log(
'action changed data:',
action,
newState.user.data,
lastData
);
lastData = newState.user.data;
}
return newState;
};
导致 user.data 不断变化的另一件事是当你在减速器中做这样的事情时:
if (action.type === SOME_TYPE) {
return {
...state,
user: {
...state.user,
//here data is set to a new array every time
data: [],
},
};
}
相反,您可以这样做:
const EMPTY_DATA = [];
//... other code
data: EMPTY_DATA,
您的选择器正在 user
脱离状态并创建一个会导致组件重新渲染的新对象,但效果的依赖性是 user.data 因此效果只会 运行 如果数据实际改变了。
Redux devtools 也以错误的方式显示差异,如果你改变状态中的某些东西,devtools 会将它们显示为更改,但 React 不会将它们视为更改。当您将新对象分配给某物时 data:[]
然后 redux 不会将它们显示为更改但 React 会将其视为更改。