reactjs - 如何防止组件被不必要地重新渲染
问题描述
我将从代码开始。我有一个类似于这个的无状态功能组件
export const Edit Topic = (_title, _text) {
const [title, setTitle] = useState(_title)
const [text, setText] = useState(_text)
return (
<>
<InputText props={{ fieldName:"Title:", value:title, setValue:setTitle, placeHolder:"Topic Title"}}/>
<InputTextArea props={{ fieldName:"Markdown Text:", text, setText }}/>
<PreviewBox text={text}/>
</>
)
}
我有PreviewBox
当它打开时,页面渲染需要更长的时间,因为text
可能会很长。PreviewBox
每次我更改文本时都需要重新渲染InputTextArea
,这很好。
我遇到的问题是,当我更改title
它的值时,它也在更新<PreviewBox/>
,这是不希望的。
如何确保<PreviewBox/>
仅在更改时更新text
而不是在title
更改时更新?
我相信重新渲染正在发生的原因是因为如果我关闭PreviewBox
,更新时没有滞后,title
但是什么时候PreviewBox
可以看到更新title
滞后。
import style from "../styles/CreateTopic.module.css"
import { Component } from "react"
import Markdown from "./Markdown";
export class PreviewBox extends Component {
constructor(props) {
super(props)
this.state = {
isShow: true
}
}
toggleShow = () => {
console.log("begin isShow", this.state)
this.setState(state => ({ isShow: !state.isShow}))
}
render() {
return (
<>
<div className={style.wrptoggle}>
<button className={style.btn} onClick={this.toggleShow}>Preview</button>
</div>
{this.state.isShow ?
<div className={style.wrppreviewbox}>
<div className={style.previewbox}>
<Markdown text={this.props.text}/>
</div>
</div>
: null}
</>
)
}
}
由于上面还包含<Markdown/>
这里的那个组件:
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";
import ReactMarkdown from "react-markdown";
import "katex/dist/katex.min.css";
const Markdown = ({text}) => {
return (
<div>
<ReactMarkdown
remarkPlugins={[remarkMath]}
rehypePlugins={[rehypeKatex]}
children={text}
/>
</div>
);
}
export default Markdown;
解决方案
我没有看到任何复杂性PreviewBox
会导致任何渲染延迟,所以我可能会假设它是在Markdown
重新渲染时可能需要一些时间“工作”的组件,因为您说“切换关闭PreviewBox
,更新时没有延迟title
”。
解决方案
您可以使用备忘录高阶组件来装饰Markdown
组件并提供自定义的areEqual
道具比较功能。
import { memo } from 'react';
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";
import ReactMarkdown from "react-markdown";
import "katex/dist/katex.min.css";
const Markdown = ({ text }) => {
return (
<div>
<ReactMarkdown
remarkPlugins={[remarkMath]}
rehypePlugins={[rehypeKatex]}
children={text}
/>
</div>
);
};
export default memo(Markdown);
默认情况下,它只会对 props 对象中的复杂对象进行浅层比较。如果要控制比较,还可以提供自定义比较函数作为第二个参数。
const areEqual = (prevProps, nextProps) => {
return prevProps.text === nextProps.text;
};
export default memo(Markdown, areEqual);
推荐阅读
- ios - Swift 如何从自定义 uicollectionviewcell 中获取数据?
- eclipse - 如何在 Eclipse 中安装 Erlide 时修复“收到致命警报:handshake_failure”错误
- python - 使用 JSON 键创建数据框
- c# - C# 使用公钥和私钥创建 RSA256 JWT
- mysql - 在开始新的更改操作之前缺少逗号。(靠近“字符集”)
- c++ - 是否存在 x + 1 == x 的 float 类型的值 x?
- vb.net - 无法在即时模式下访问 Word 类的类成员
- java - PageFactory 初始化问题
- python - 如何捕获异常 MaxRetryError?
- c++ - ESP8266 I2C 从机不确认数据