是否有系统的方法来调试导致组件在React中重新呈现的原因?我放了一个简单的console.log()来查看它呈现了多少时间,但我很难弄清楚是什么原因导致组件呈现多次,即(4次)在我的情况下。是否有一个工具可以显示时间轴和/或所有组件树的渲染和顺序?
当前回答
奇怪的是没有人给出这个答案,但我发现它非常有用,特别是因为道具的变化几乎总是深嵌套的。
钩子粉丝:
import deep_diff from "deep-diff";
const withPropsChecker = WrappedComponent => {
return props => {
const prevProps = useRef(props);
useEffect(() => {
const diff = deep_diff.diff(prevProps.current, props);
if (diff) {
console.log(diff);
}
prevProps.current = props;
});
return <WrappedComponent {...props} />;
};
};
“老”平衡粉丝:
import deep_diff from "deep-diff";
componentDidUpdate(prevProps, prevState) {
const diff = deep_diff.diff(prevProps, this.props);
if (diff) {
console.log(diff);
}
}
附注:我仍然更喜欢使用HOC(高阶组件),因为有时你在顶部解构了你的道具,Jacob的解决方案不太适合
免责声明:与包所有者没有任何联系。只是点击数十次,试图找出深嵌套对象之间的差异,这是一种痛苦。
其他回答
使用钩子和功能组件,而不仅仅是道具的改变会导致渲染。我开始使用的是一个相当手动的日志。这对我帮助很大。你可能也会发现它很有用。
我将这部分复制到组件的文件中:
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组件将重新渲染的一些实例。
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或无状态组件。纯的和无状态的组件只有在它的道具发生变化时才会重新渲染。
如果你想要一个没有任何外部依赖的简短片段,我发现这很有用
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>;
}
上面的答案非常有用,如果有人正在寻找一种特定的方法来检测重新渲染的原因,那么我发现这个库redux-logger非常有用。
你能做的就是添加库并启用状态差异(它在文档中),如下所示:
const logger = createLogger({
diff: true,
});
并在存储中添加中间件。
然后在要测试的组件的渲染函数中放入console.log()。
然后,您可以运行应用程序并检查控制台日志。无论在哪里有一个日志之前,它都会显示状态(nextProps和this.props)之间的差异,你可以决定是否真的需要渲染
它将类似于上面的图像连同diff键。
你可以使用React Devtools profiler工具检查组件(重新)渲染的原因。不需要更改代码。请参阅react团队的博客文章介绍react分析器。
首先,转到设置cog > profiler,并选择“记录每个组件渲染的原因”
推荐文章
- npm犯错!代码UNABLE_TO_GET_ISSUER_CERT_LOCALLY
- 反应-显示加载屏幕,而DOM是渲染?
- 如何解决“不能在模块外使用导入语句”在开玩笑
- 是否有可能在react渲染函数中返回空?
- 使用Redux而不是Flux的缺点是什么
- 反应:为什么当道具改变时子组件不更新
- React vs ReactDOM?
- Axios -删除请求与请求体和头?
- “react-scripts”不被视为内部或外部命令
- 如何从状态数组中删除一个项目?
- 是否可以用if…else…语句在React渲染函数?
- 如何设置默认的复选框ReactJS?
- 反应。类型无效——期望为字符串
- 如何动态地将一个类添加到手动类名?
- 无效的钩子调用。钩子只能在函数组件的内部调用