прочитать файл JSON с локального жесткого диска и проанализировать приложение реакции - PullRequest
2 голосов
/ 11 октября 2019

Я пытаюсь прочитать файл JSON с жесткого диска, который был выбран пользователем или перетащен. Я немного не уверен, как это должно работать, и я думаю, что у меня проблема с тем, что FileReader.readAsText является асинхронным. В любом случае, сделал компонент Drop Zone, который отлично работает, и пользователи также могут выбрать файл. Вот соответствующие части моего кода:

const DropZone = () => {
  const [files, setFiles] = useState([]);
  const [parsedFile, setParsedFile] = useState(null);

  const onDrop = async (e) => {
    e.preventDefault();
    if (disabled) return;
    setFiles([...e.dataTransfer.files]);

    const fileReader = new FileReader();

    await fileReader.readAsText(e.dataTransfer.files[0]);

    fileReader.onload = (e) => {
      setParsedFile(JSON.parse(e.target.result));
    };

    // e.dataTransfer.clearData();
    // setDragging(false);
  };

  const renderHasFiles = () => {
    // console.log('files: ', files);
    return (
      <Fragment>
        <StyledIcon iconName="cloud_done" size="extraLarge" color={alertColors.SUCCESS} />
        <div>Got em!</div>
        <FileList>
          <FileListHeader>
            <TableHeader>File Name</TableHeader>
            <TableHeader align="right">Size</TableHeader>
          </FileListHeader>
          <FileListContent>
            {renderFileList()}
          </FileListContent>
        </FileList>
        <ButtonContainer>
          <ClearButton onClick={(e) => {e.preventDefault(); e.stopPropagation(); setFiles([]);}}>
            Clear Files
          </ClearButton>
          <StyledButton onClick={(e) => { e.preventDefault(); e.stopPropagation(); submitButtonCallback(files, parsedFile); }}>
            {submitButtonText}
          </StyledButton>
        </ButtonContainer>
      </Fragment>
    );
  };

  return (
    <DropZoneContainer
      width={width}
      height={height}
      disabled={disabled}
      dragging={dragging}
      onClick={() => openFileDialog()}
      onDragOver={(e) => onDragOver(e)}
      onDrop={(e) => onDrop(e)}
    >
      {files.length === 0 ? renderNoFiles() : renderHasFiles()}
    </DropZoneContainer>
  );
};

Журнал консоли parsedFile равен нулю, но если я задаю оператор отладчика в onload, я могу видеть содержимое читаемого файла. Почему я не могу достать содержимое файла?

Ответы [ 2 ]

1 голос
/ 11 октября 2019

опечатка в:

const [parsedFile, setParsedFile] = useState(null);

код считывателя файлов:

const fileReader = new FileReader();

fileReader.readAsText(e.dataTransfer.files[0]);

fileReader.onload = () => {
  setParsedFile(fileReader.result);
};
1 голос
/ 11 октября 2019

Вы пытаетесь напечатать parsedFile, но в состоянии это называется parsedFiled. Вы также печатаете значение до того, как обратный вызов onload установит состояние. Попробуйте переместить печать в функцию обратного вызова.

Функция обратного вызова onload является асинхронной, поэтому вы не можете использовать значение сразу после его вызова, поскольку нет гарантии, что функция разрешена. Чтобы использовать содержимое файла, вы можете выполнить одно из следующих действий: поместить соответствующий код в функцию рендеринга, чтобы он мог реагировать на изменение состояния;написать код и вставить его в функцию обратного вызова, чтобы он вызывался, когда доступно содержимое;используйте функцию синхронного чтения или оберните асинхронную функцию в обещание, чтобы вы могли иметь представление о том, как оно разрешается (например, await обещание и использовать его содержимое сразу после).

...