React перехватывает компонент обратного вызова только имеет начальное состояние - PullRequest
1 голос
/ 12 апреля 2020

Я новичок в реагировании хуков, однако у меня есть проблема, которая, я думаю, довольно проста. Вот мой родительский компонент:

import React, { useState, useEffect } from 'react';
import DragAndDrop from '../DragAndDrop';
import Attachment from './Attachment';
import API from '../../services/api';
import '../../styles/components/attachments.scss';

const api = API.create();

const Attachments = ({attachments, type, typeId}) => {

  const [attachmentData, setAttachmentData] = useState([]);

  useEffect(() => {
    setAttachmentData(attachments);
  }, [attachments])

  function onUpload(files) {
    if (typeId) {
      api.AddAttachment(type, typeId, files).then(response => {
        let newAttachments = response.data.data;
        let newAttachmentData = attachmentData;
        newAttachmentData = newAttachmentData.concat(newAttachments);
        setAttachmentData(newAttachmentData);
      });
    }
  }

  return (
    <div className="attachments">
      <h3 className="attachments-title">Attachments</h3>
      <DragAndDrop onUpload={onUpload} />
      {attachmentData.map((attachment, index) => (
        <Attachment key={index} attachment={attachment} />
      ))}
    </div>
  );
}

export default Attachments;

attachments передается из родительского компонента asyn c, поэтому я использую функцию useEffect.

Это все работает нормально, а дочерние компоненты Attachment отображаются при получении данных.

У меня есть обратный вызов onUpload, который вызывается из компонента DragAndDrop:

import React, { useCallback } from 'react';
import {useDropzone} from 'react-dropzone';
import '../styles/components/dragAndDrop.scss';

const DragAndDrop = ({onUpload}) => {

  const onDrop = useCallback(acceptedFiles => {
    onUpload(acceptedFiles);
  }, [])

  const {getRootProps, getInputProps} = useDropzone({onDrop});

  return (
    <div>
      <div {...getRootProps({className: 'dropzone'})}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>
    </div>
  );

};

export default DragAndDrop;

Моя проблема заключается в том, что при вызове обратного вызова onUpload в компоненте Attachments attachmentData является исходной значение, которое является пустым массивом вместо того, чтобы быть заполненным вложениями. В моей функции onUpload я публикую новые загрузки в мой API, который затем возвращает их в том же формате, что и остальные вложения. Затем я хочу присоединить эти новые приложения к attachmentData. Мне нужно attachmentData, чтобы заполнить его значением в обратном вызове. Почему attachmentData исходное состояние []? Как мне заставить это работать?

1 Ответ

2 голосов
/ 12 апреля 2020

Проблема в том, что вы получаете доступ к attachmentData в onUpload, который становится устаревшим к тому времени, когда вы его используете, поэтому, чтобы получить последнюю attachmentData, вы можете передать функцию обратного вызова вашей функции обновления setAttachmentData, например this:

  function onUpload(files) {
    if (typeId) {
      api.AddAttachment(type, typeId, files).then(response => {
        let newAttachments = response.data.data;
        setAttachmentData(prevAttachmentData => ([...prevAttachmentData, ...newAttachments]));
      });
    }
  }

Если вы хотите получить доступ к attachmentsData внутри onUpload, вы можете сделать это, создав ссылку и затем обновляя эту ссылку каждый раз, когда attachmentsData изменяется, таким образом, вам не придется передайте функцию setAttachmentsData также:

const [attachmentsData, setAttachmentsData] = React.useState([]);
const attachmentsDataRef = React.useRef(attachmentsData);

// Update ref whenever state changes
useEffect(() => {
  attachmentsDataRef.current = attachmentsData;
}, [attachmentsData]);

// Now in onUpload
 function onUpload(files) {
    // Here you can access attachmentsDataRef.current and you'll get updated state everytime
    if (typeId) {
      api.AddAttachment(type, typeId, files).then(response => {
        let newAttachments = response.data.data;
        setAttachmentData([...attachmentsDataRef.current, ...newAttachments]);
      });
    }
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...