использовать код componentDidUpdate вместе с DidMount и UnMount в useEffect - PullRequest
0 голосов
/ 20 января 2019

Я пытаюсь перенести мой код в новый реагирующий, который поддерживает реагирующие хуки. Я использую 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);
        }

1 Ответ

0 голосов
/ 20 января 2019

Если намерение состоит в том, чтобы избежать ненужных обновлений при получении одинаковых реквизитов, и это относится ко всем реквизитам, а не только к 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])
...