是否有系统的方法来调试导致组件在React中重新呈现的原因?我放了一个简单的console.log()来查看它呈现了多少时间,但我很难弄清楚是什么原因导致组件呈现多次,即(4次)在我的情况下。是否有一个工具可以显示时间轴和/或所有组件树的渲染和顺序?
当前回答
你可以使用React Devtools profiler工具检查组件(重新)渲染的原因。不需要更改代码。请参阅react团队的博客文章介绍react分析器。
首先,转到设置cog > profiler,并选择“记录每个组件渲染的原因”
其他回答
使用钩子和功能组件,而不仅仅是道具的改变会导致渲染。我开始使用的是一个相当手动的日志。这对我帮助很大。你可能也会发现它很有用。
我将这部分复制到组件的文件中:
const keys = {};
const checkDep = (map, key, ref, extra) => {
if (keys[key] === undefined) {
keys[key] = {key: key};
return;
}
const stored = map.current.get(keys[key]);
if (stored === undefined) {
map.current.set(keys[key], ref);
} else if (ref !== stored) {
console.log(
'Ref ' + keys[key].key + ' changed',
extra ?? '',
JSON.stringify({stored}).substring(0, 45),
JSON.stringify({now: ref}).substring(0, 45),
);
map.current.set(keys[key], ref);
}
};
在方法的开头,我保留了一个WeakMap引用:
const refs = useRef(new WeakMap());
然后在每个“可疑的”电话(道具,钩子)之后,我写道:
const example = useExampleHook();
checkDep(refs, 'example ', example);
你可以使用React Devtools profiler工具检查组件(重新)渲染的原因。不需要更改代码。请参阅react团队的博客文章介绍react分析器。
首先,转到设置cog > profiler,并选择“记录每个组件渲染的原因”
感谢https://stackoverflow.com/a/51082563/2391795的回答,我已经提出了这个稍微不同的解决方案仅功能组件(TypeScript),它也处理状态,而不仅仅是道具。
import {
useEffect,
useRef,
} from 'react';
/**
* Helps tracking the props changes made in a react functional component.
*
* Prints the name of the properties/states variables causing a render (or re-render).
* For debugging purposes only.
*
* @usage You can simply track the props of the components like this:
* useRenderingTrace('MyComponent', props);
*
* @usage You can also track additional state like this:
* const [someState] = useState(null);
* useRenderingTrace('MyComponent', { ...props, someState });
*
* @param componentName Name of the component to display
* @param propsAndStates
* @param level
*
* @see https://stackoverflow.com/a/51082563/2391795
*/
const useRenderingTrace = (componentName: string, propsAndStates: any, level: 'debug' | 'info' | 'log' = 'debug') => {
const prev = useRef(propsAndStates);
useEffect(() => {
const changedProps: { [key: string]: { old: any, new: any } } = Object.entries(propsAndStates).reduce((property: any, [key, value]: [string, any]) => {
if (prev.current[key] !== value) {
property[key] = {
old: prev.current[key],
new: value,
};
}
return property;
}, {});
if (Object.keys(changedProps).length > 0) {
console[level](`[${componentName}] Changed props:`, changedProps);
}
prev.current = propsAndStates;
});
};
export default useRenderingTrace;
注意,实现本身并没有太大变化。文档展示了如何在道具/状态和组件中使用它,现在该组件是用TypeScript编写的。
如果你想要一个没有任何外部依赖的简短片段,我发现这很有用
componentDidUpdate(prevProps, prevState) {
Object.entries(this.props).forEach(([key, val]) =>
prevProps[key] !== val && console.log(`Prop '${key}' changed`)
);
if (this.state) {
Object.entries(this.state).forEach(([key, val]) =>
prevState[key] !== val && console.log(`State '${key}' changed`)
);
}
}
下面是我用来跟踪函数组件更新的一个小钩子
function useTraceUpdate(props) {
const prev = useRef(props);
useEffect(() => {
const changedProps = Object.entries(props).reduce((ps, [k, v]) => {
if (prev.current[k] !== v) {
ps[k] = [prev.current[k], v];
}
return ps;
}, {});
if (Object.keys(changedProps).length > 0) {
console.log('Changed props:', changedProps);
}
prev.current = props;
});
}
// Usage
function MyComponent(props) {
useTraceUpdate(props);
return <div>{props.children}</div>;
}
下面是React组件将重新渲染的一些实例。
Parent component rerender Calling this.setState() within the component. This will trigger the following component lifecycle methods shouldComponentUpdate > componentWillUpdate > render > componentDidUpdate Changes in component's props. This will trigger componentWillReceiveProps > shouldComponentUpdate > componentWillUpdate > render > componentDidUpdate (connect method of react-redux trigger this when there are applicable changes in the Redux store) calling this.forceUpdate which is similar to this.setState
您可以通过在shouldComponentUpdate中实现检查来最小化组件的渲染器,如果不需要,则返回false。
另一种方法是使用React。PureComponent或无状态组件。纯的和无状态的组件只有在它的道具发生变化时才会重新渲染。
推荐文章
- 这个“react-scripts eject”命令是做什么的?
- js:将一个组件包装成另一个组件
- 在typescript中一直使用。tsx而不是。ts有什么缺点吗?
- TypeScript React应用程序中的PropTypes
- {this.props是什么?孩子们,什么时候应该使用它?
- 反应。useState不会从props中重新加载状态
- 在Link react-router中传递道具
- React不会加载本地图像
- Axios获取url工作,但第二个参数作为对象,它不
- 我如何使用多个引用的元素与挂钩数组?
- 组件中useState对状态更新器的多次调用会导致多次重渲染
- 什么是useState()在React?
- 如何使webpack开发服务器运行在端口80和0.0.0.0使其公开访问?
- 无法找到模块“react-materialize”的声明文件。` path/to/module-name.js `隐式具有any类型
- 如何从子组件内部更新React上下文?