是否有系统的方法来调试导致组件在React中重新呈现的原因?我放了一个简单的console.log()来查看它呈现了多少时间,但我很难弄清楚是什么原因导致组件呈现多次,即(4次)在我的情况下。是否有一个工具可以显示时间轴和/或所有组件树的渲染和顺序?
当前回答
@jpdelatorre的回答很好地强调了React组件可能重新渲染的一般原因。
我只是想更深入地探讨一个例子:当道具改变时。找出导致React组件重新渲染的原因是一个常见的问题,根据我的经验,很多时候追踪这个问题需要确定哪些道具发生了变化。
React组件在接收到新道具时重新渲染。他们可以收到新的道具,比如:
<MyComponent prop1={currentPosition} prop2={myVariable} />
或者如果MyComponent连接到redux存储:
function mapStateToProps (state) {
return {
prop3: state.data.get('savedName'),
prop4: state.data.get('userCount')
}
}
只要prop1、prop2、prop3或prop4的值发生变化,MyComponent就会重新呈现。对于4个道具,通过在渲染块的开头放置console.log(this.props)来跟踪哪些道具正在改变并不太难。但随着部件越来越复杂,道具越来越多,这种方法就站不住脚了。
下面是一个有用的方法(为了方便使用lodash)来确定哪些道具更改导致组件重新渲染:
componentWillReceiveProps (nextProps) {
const changedProps = _.reduce(this.props, function (result, value, key) {
return _.isEqual(value, nextProps[key])
? result
: result.concat(key)
}, [])
console.log('changedProps: ', changedProps)
}
将这个片段添加到组件中可以帮助揭示导致可疑的重新呈现的罪魁祸首,而且很多时候这有助于揭示注入组件的不必要数据。
其他回答
感谢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编写的。
@jpdelatorre的回答很好地强调了React组件可能重新渲染的一般原因。
我只是想更深入地探讨一个例子:当道具改变时。找出导致React组件重新渲染的原因是一个常见的问题,根据我的经验,很多时候追踪这个问题需要确定哪些道具发生了变化。
React组件在接收到新道具时重新渲染。他们可以收到新的道具,比如:
<MyComponent prop1={currentPosition} prop2={myVariable} />
或者如果MyComponent连接到redux存储:
function mapStateToProps (state) {
return {
prop3: state.data.get('savedName'),
prop4: state.data.get('userCount')
}
}
只要prop1、prop2、prop3或prop4的值发生变化,MyComponent就会重新呈现。对于4个道具,通过在渲染块的开头放置console.log(this.props)来跟踪哪些道具正在改变并不太难。但随着部件越来越复杂,道具越来越多,这种方法就站不住脚了。
下面是一个有用的方法(为了方便使用lodash)来确定哪些道具更改导致组件重新渲染:
componentWillReceiveProps (nextProps) {
const changedProps = _.reduce(this.props, function (result, value, key) {
return _.isEqual(value, nextProps[key])
? result
: result.concat(key)
}, [])
console.log('changedProps: ', changedProps)
}
将这个片段添加到组件中可以帮助揭示导致可疑的重新呈现的罪魁祸首,而且很多时候这有助于揭示注入组件的不必要数据。
你可以使用React Devtools profiler工具检查组件(重新)渲染的原因。不需要更改代码。请参阅react团队的博客文章介绍react分析器。
首先,转到设置cog > profiler,并选择“记录每个组件渲染的原因”
上面的答案非常有用,如果有人正在寻找一种特定的方法来检测重新渲染的原因,那么我发现这个库redux-logger非常有用。
你能做的就是添加库并启用状态差异(它在文档中),如下所示:
const logger = createLogger({
diff: true,
});
并在存储中添加中间件。
然后在要测试的组件的渲染函数中放入console.log()。
然后,您可以运行应用程序并检查控制台日志。无论在哪里有一个日志之前,它都会显示状态(nextProps和this.props)之间的差异,你可以决定是否真的需要渲染
它将类似于上面的图像连同diff键。
下面是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不会加载本地图像
- Axios获取url工作,但第二个参数作为对象,它不
- 我如何使用多个引用的元素与挂钩数组?
- 组件中useState对状态更新器的多次调用会导致多次重渲染
- 什么是useState()在React?
- 如何使webpack开发服务器运行在端口80和0.0.0.0使其公开访问?
- 无法找到模块“react-materialize”的声明文件。` path/to/module-name.js `隐式具有any类型
- 如何从子组件内部更新React上下文?
- 不能在呈现不同组件警告时更新组件
- 如何在react-router中以编程方式更新查询参数?
- 对象作为React子对象无效。如果要呈现子元素的集合,请使用数组
- Redux @connect装饰器中的“@”(at符号)是什么?
- 如何有条件元素和保持干燥与Facebook React的JSX?
- “你正在运行create-react-app 4.0.3,它落后于最新版本(5.0.0)”
- 道具更新状态在React Form中发生变化