这是weathercard.jsx的代码,当它加载时以及当我检查日志时,组件会渲染多次
import React, { useState, memo } from "react";
import { NavLink } from "react-router-dom";
import HighlightText from "./utility/HighlighText";
import { weatherData } from "./test";
const WeatherCard = memo(({ arrow, title, routeCard, text, flightDetails }) => {
const [toggleCard, setToggleCard] = useState(false);
const weatherDataAtis = weatherData["d-atis"];
const metar = flightDetails.metar;
const taf = flightDetails.taf;
const datis = flightDetails.datis;
const coloredText = HighlightText({
text: weatherDataAtis.dataString,
highlightedPhrases: weatherDataAtis.highlight,
});
const handleToggleCard = () => {
setToggleCard((prev) => !prev);
};
if (routeCard)
return (
<div className="card">
<h3 className="card__title">
{arrow ? "▼" : null} {title}
<NavLink
to="https://skyvector.com/?fpl=%20KEWR%20LANNA%20J48%20CSN%20FANPO%20Q40%20AEX%20DOOBI2%20KIAH"
className="card__route__link"
target="_blank"
rel="noopener noreferrer"
>
Show on SkyVector Map
</NavLink>
</h3>
<div className="card__route">
<div className="card__route__text">{text}</div>
</div>
</div>
);
if (weatherData) {
const { METAR, TAF, D_ATIS, name } = flightDetails || {};
return (
<>
<h3 className="weather__title">
<span>Weather for </span> {name}
</h3>
<div className="card">
<div>
<div className="card__depature__subtitle card__header--dark">
<h3 className="card__depature__subtitle__title">D-ATIS </h3>
<span className="card__depature__time">34 mins ago</span>
</div>
<div className="card__depature__details">
<p>{datis}</p>
</div>
<div className="card__depature__subtitle card__header--dark">
<h3 className="card__depature__subtitle__title">METAR</h3>
<span className="card__depature__time">34 mins ago</span>
</div>
<div className="card__depature__details">
<p>{metar}</p>
</div>
<div className="card__depature__subtitle card__header--dark">
<h3 className="card__depature__subtitle__title">TAF</h3>
<span className="card__depature__time">166 mins ago</span>
</div>
<div className="card__depature__details">
<p>{taf}</p>
</div>
</div>
</div>
</>
);
}
return (
<div className="card">
<h3 className="card__title" onClick={handleToggleCard}>
{arrow ? "▼" : null} {title}
</h3>
<div className={toggleCard ? null : "card__body"}>
<div className="card__depature__subtitle">
<h3 className="card__depature__subtitle__title">D-ATIS </h3>
<span className="card__depature__time">34 mins ago</span>
</div>
<div className="card__depature__details">
<p></p>
</div>
<div className="card__depature__subtitle">
<h3 className="card__depature__subtitle__title">METAR</h3>
<span className="card__depature__time">34 mins ago</span>
</div>
<div className="card__depature__details">
<p></p>
</div>
<div className="card__depature__subtitle">
<h3 className="card__depature__subtitle__title">TAF</h3>
<span className="card__depature__time">166 mins ago</span>
</div>
<div className="card__depature__details">
<p></p>
</div>
</div>
</div>
);
});
export default WeatherCard;
这是日志
Details.jsx 中的 searchValue {value: '纽瓦克自由国际机场 (EWR)', 标签: '纽瓦克自由国际机场 (EWR)', 名称: '纽瓦克自由国际机场', 代码: 'EWR', id: '66176711170d1d57a24dfb23 '} Details.jsx:Details.jsx中的19 searchValue {值:'纽瓦克自由国际机场(EWR)',标签:'纽瓦克自由国际机场(EWR)',名称:'纽瓦克自由国际机场',代码:'EWR', id: '66176711170d1d57a24dfb23'}
Details.jsx:来自Details.jsx的32 res.data {metar:'KEWR 281751Z 27008G24KT 10SM FEW045 FEW130 SCT180 …993 RMK AO2 SLP136 T03280211 10333 20244 56013 $ ', taf: 'KEWR 291732Z 2918/3024 09007KT P6SM SCT030 BKN040 …P6SM SCT025 BKN050 PROB30 3018/3024 6SM-SHRA ',数据:'EWR ATIS INFO C 1751Z。 07005KT 10SM OVC032 26/17 操作和指定的替代项。 ...您有信息 C.'} Details.jsx:来自Details.jsx的32 res.data {metar:'KEWR 281751Z 27008G24KT 10SM FEW045 FEW130 SCT180 …993 RMK AO2 SLP136 T03280211 10333 20244 56013 $ ', taf: 'KEWR 291732Z 2918/3024 09007KT P6SM SCT030 BKN040 …P6SM SCT025 BKN050 PROB30 3018/3024 6SM-SHRA ',数据:'EWR ATIS INFO C 1751Z。 07005KT 10SM OVC032 26/17 操作和指定的替代项。 ...ADVS 您有信息 C.'}
我也会附上屏幕截图在此处输入图像描述
为什么组件会多次渲染,与使用效果有什么关系,还是生产环境和开发环境中的 javascript 加载方式不同?
组件多次渲染的问题可能是由于多种因素造成的,特别是在使用 React 的 useState 或 useEffect 钩子时。以下是一些可能的原因和建议,以减少不必要的重新渲染:
1。道具变更 React.memo 仅当传递给组件的 props 保持不变时才阻止重新渲染。如果任何 prop 发生变化,即使是轻微变化,组件也会重新渲染。 检查箭头、标题、路线卡、文本或航班详细信息在每次渲染时是否发生变化。如果它们源自父组件的状态或道具,则它们可能会导致重新渲染。
解决方案:确保不会在父组件中的每个渲染上不必要地重新创建道具。例如,在父组件中使用 useMemo 或 useCallback 来记忆 props 可能会有所帮助。
2。内部状态更新 状态更新:每当调用 setToggleCard 时,都会导致组件重新渲染。即使状态值相同,React 仍然会重新渲染。 确保不会多次使用相同的值调用 setToggleCard。
解决方案: 仅当状态确实需要更改时才调用 setToggleCard。
<pre><code>
const handleToggleCard = () => {
setToggleCard((prev) => !prev);
};
</pre></code>
他应该没问题,因为它会翻转布尔值,但您可以在调用 setToggleCard 之前记录该值,以确保它不会被意外触发。
3.高亮文本功能 如果HighlightText实用函数的计算量很大,那么最好记住它的结果。
解决方案:使用useMemo来记忆彩色文本。
<pre><code>
const coloredText = useMemo(() => HighlightText({
text: weatherDataAtis.dataString,
highlightedPhrases: weatherDataAtis.highlight,
}), [weatherDataAtis.dataString, weatherDataAtis.highlight]);
</pre></code>
4。航班详细信息对象 确保 FlightDetails 是一个稳定的对象,并且不会在父组件中的每个渲染中重新创建。
解决方案:如果在父组件中动态创建flightDetails,请确保它已被记忆或使用useEffect仅在其依赖项发生变化时更新。
5。天气数据检查 您有一个条件检查 if (weatherData)。如果这个值改变,会导致重新渲染。
解决方案:确保天气数据不会发生不必要的变异或更新。
6。反应严格模式 如果您在 StrictMode 的开发模式下使用 React,React 可能会故意渲染组件两次以帮助检测副作用。在生产模式下不会发生这种情况。
总结 确保传递给 WeatherCard 的 props 稳定且不会发生不必要的更改。 使用 useMemo 来处理计算量大的函数或值。 避免不必要的状态更新。 开发中要注意React的StrictMode,这可能会导致故意重新渲染。 通过这些调整,您应该会看到不必要的重新渲染的减少。