Reputation: 1998
I'll start with the code. I have a stateless functional component that resembles this
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}/>
</>
)
}
I have PreviewBox
when it's on, page rendering takes a bit longer because text
can be quite long. PreviewBox
needs to re-render each time I change text in InputTextArea
and that's fine.
The problem I'm having is when I change the value of title
it's also updating <PreviewBox/>
which is undesired.
How can I make sure that <PreviewBox/>
only updates when text
changes and not when title
changes?
The reason why I believe the re-rendering is occuring is because if I toggle off PreviewBox
, there's no lag in when updating title
but when PreviewBox
is visible the updating the title
lags.
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}
</>
)
}
}
Since the above also contains <Markdown/>
here's that component:
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;
Upvotes: 1
Views: 515
Reputation: 203512
I don't see any complexity in PreviewBox
that would cause any rendering delay so I might assume it's the Markdown
component that may take some time "working" when it's rerendered since you say "toggle off PreviewBox
, there's no lag in when updating title
".
You can use the memo Higher Order Component to decorate the Markdown
component and provide a custom areEqual
props compare function.
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);
By default it will only shallowly compare complex objects in the props object. If you want control over the comparison, you can also provide a custom comparison function as the second argument.
const areEqual = (prevProps, nextProps) => {
return prevProps.text === nextProps.text;
};
export default memo(Markdown, areEqual);
Upvotes: 1