在 useEffect 中使用 componentDidUpdate 代码以及 DidMount 和 UnMount
use componentDidUpdate code along with DidMount and UnMount in useEffect
我正在尝试将我的代码迁移到支持反应钩子的新反应。我正在使用 useReducer、useState 和 useEffect。我可以在我的代码中使用 DidMount
和 UnMount
但不知道我如何实现 DidUpdate
部分,因为这可能会造成重新渲染问题。
这是我的做法
旧代码
class ImageBoard extends React.Component {
constructor() {
super();
this.state = {
canvas: undefined,
selected: undefined
};
}
handleDeleteKey(event) {
if (event.keyCode === 46 || event.keyCode === 8) {
event.preventDefault();
if (this.state.selected !== undefined) {
this.state.canvas.remove(this.state.selected);
this.setState({ selected: undefined });
}
}
}
componentDidMount() {
const canvas = new fabric.Canvas("canvas");
document.addEventListener("keydown",this.handleDeleteKey.bind(this),false);
canvas.on("object:selected", e => this.setState({ selected: e.target }));
canvas.on("selection:cleared", e => this.setState({ selected: undefined }));
this.setState({ canvas: canvas });
this.setCanvasBackground(this.props.getSelectedImage, canvas);
}
componentDidUpdate(prevProps) {
if (prevProps.getSelectedImage !== this.props.getSelectedImage) {
this.setCanvasBackground(this.props.getSelectedImage,this.state.canvas);
}
}
更改为以下新代码
const ImageBoard = () => {
let canvasEl = React.useRef(null);
const [selected, setSelected] = React.useState(null)
const [canvas, setCanvas] = React.useState(null)
const [state, _] = React.useReducer(imagesReducer, [])
const handleDeleteKey = event => {
if (event.keyCode === 46 || event.keyCode === 8) {
event.preventDefault();
if (selected !== undefined) {
canvas.remove(selected);
setSelected(undefined);
}
}
}
React.useEffect(() => {
const canvas = new fabric.Canvas("canvas");
document.addEventListener(
"keydown",
handleDeleteKey,
false
);
canvas.on("object:selected", e => setSelected(e.target));
canvas.on("selection:cleared", e => setSelected(undefined));
setCanvas(canvas);
setCanvasBackground(state.images.selectedImage, canvas);
return () => {
document.removeEventListener("keydown", handleDeleteKey, false);
}
}, [])
如何在 useEffect 中编写以下代码片段?
componentDidUpdate(prevProps) {
if (prevProps.getSelectedImage !== this.props.getSelectedImage) {
this.setCanvasBackground(this.props.getSelectedImage,this.state.canvas);
}
this.setCanvasBackground(this.props.getSelectedImage,this.state.canvas);
}
如果目的是避免在接收到相同的 props 时进行不必要的更新,并且这适用于所有 props 而不仅仅是 getSelectedImage
,则可以将组件设为纯组件:
const ImageBoard = memo(props => { ... });
所以组件只会在收到新的道具时重新渲染,包括useEffect
:
useEffect(() => {
// runs every time the component is rendered
setCanvasBackground(props.getSelectedImage, canvas);
})
如果仅当接收到特定属性的新值时才评估组件的一部分,例如 getSelectedImage
,这将通过 useMemo
或 useEffect
挂钩完成,具体取决于案件。由于 useEffect
可以同时充当 componentDidUpdate
和 componentDidMount
,因此应该考虑到这一点。
useEffect(() => {
// runs once on mount
const canvas = new fabric.Canvas("canvas");
document.addEventListener(
"keydown",
handleDeleteKey,
false
);
canvas.on("object:selected", e => setSelected(e.target));
canvas.on("selection:cleared", e => setSelected(undefined));
setCanvas(canvas);
// setCanvasBackground is moved to another hook
return () => {
document.removeEventListener("keydown", handleDeleteKey, false);
}
}, [])
useEffect(() => {
// runs every time new getSelectedImage is received, including initial render
setCanvasBackground(props.getSelectedImage, canvas);
}, [props.getSelectedImage])
我正在尝试将我的代码迁移到支持反应钩子的新反应。我正在使用 useReducer、useState 和 useEffect。我可以在我的代码中使用 DidMount
和 UnMount
但不知道我如何实现 DidUpdate
部分,因为这可能会造成重新渲染问题。
这是我的做法
旧代码
class ImageBoard extends React.Component {
constructor() {
super();
this.state = {
canvas: undefined,
selected: undefined
};
}
handleDeleteKey(event) {
if (event.keyCode === 46 || event.keyCode === 8) {
event.preventDefault();
if (this.state.selected !== undefined) {
this.state.canvas.remove(this.state.selected);
this.setState({ selected: undefined });
}
}
}
componentDidMount() {
const canvas = new fabric.Canvas("canvas");
document.addEventListener("keydown",this.handleDeleteKey.bind(this),false);
canvas.on("object:selected", e => this.setState({ selected: e.target }));
canvas.on("selection:cleared", e => this.setState({ selected: undefined }));
this.setState({ canvas: canvas });
this.setCanvasBackground(this.props.getSelectedImage, canvas);
}
componentDidUpdate(prevProps) {
if (prevProps.getSelectedImage !== this.props.getSelectedImage) {
this.setCanvasBackground(this.props.getSelectedImage,this.state.canvas);
}
}
更改为以下新代码
const ImageBoard = () => {
let canvasEl = React.useRef(null);
const [selected, setSelected] = React.useState(null)
const [canvas, setCanvas] = React.useState(null)
const [state, _] = React.useReducer(imagesReducer, [])
const handleDeleteKey = event => {
if (event.keyCode === 46 || event.keyCode === 8) {
event.preventDefault();
if (selected !== undefined) {
canvas.remove(selected);
setSelected(undefined);
}
}
}
React.useEffect(() => {
const canvas = new fabric.Canvas("canvas");
document.addEventListener(
"keydown",
handleDeleteKey,
false
);
canvas.on("object:selected", e => setSelected(e.target));
canvas.on("selection:cleared", e => setSelected(undefined));
setCanvas(canvas);
setCanvasBackground(state.images.selectedImage, canvas);
return () => {
document.removeEventListener("keydown", handleDeleteKey, false);
}
}, [])
如何在 useEffect 中编写以下代码片段?
componentDidUpdate(prevProps) {
if (prevProps.getSelectedImage !== this.props.getSelectedImage) {
this.setCanvasBackground(this.props.getSelectedImage,this.state.canvas);
}
this.setCanvasBackground(this.props.getSelectedImage,this.state.canvas);
}
如果目的是避免在接收到相同的 props 时进行不必要的更新,并且这适用于所有 props 而不仅仅是 getSelectedImage
,则可以将组件设为纯组件:
const ImageBoard = memo(props => { ... });
所以组件只会在收到新的道具时重新渲染,包括useEffect
:
useEffect(() => {
// runs every time the component is rendered
setCanvasBackground(props.getSelectedImage, canvas);
})
如果仅当接收到特定属性的新值时才评估组件的一部分,例如 getSelectedImage
,这将通过 useMemo
或 useEffect
挂钩完成,具体取决于案件。由于 useEffect
可以同时充当 componentDidUpdate
和 componentDidMount
,因此应该考虑到这一点。
useEffect(() => {
// runs once on mount
const canvas = new fabric.Canvas("canvas");
document.addEventListener(
"keydown",
handleDeleteKey,
false
);
canvas.on("object:selected", e => setSelected(e.target));
canvas.on("selection:cleared", e => setSelected(undefined));
setCanvas(canvas);
// setCanvasBackground is moved to another hook
return () => {
document.removeEventListener("keydown", handleDeleteKey, false);
}
}, [])
useEffect(() => {
// runs every time new getSelectedImage is received, including initial render
setCanvasBackground(props.getSelectedImage, canvas);
}, [props.getSelectedImage])