简体   繁体   中英

Component looping over infinitely after updating state

I'm trying to update state under a promise. But the component is going over and over again infinitely until it max out the heap size. I don't know what I'm missing here. This is my code

import {useDropzone} from 'react-dropzone';
import File from './File'
import parser from 'subtitles-parser'

const baseStyle = {
  flex: 1,
  display: 'flex',
  flexDirection: 'column',
  alignItems: 'center',
  padding: '20px',
  borderWidth: 2,
  borderRadius: 2,
  borderColor: '#eeeeee',
  borderStyle: 'dashed',
  backgroundColor: '#fafafa',
  color: '#bdbdbd',
  outline: 'none',
  transition: 'border .24s ease-in-out'
};

const activeStyle = {
  borderColor: '#2196f3'
};

const acceptStyle = {
  borderColor: '#00e676'
};

const rejectStyle = {
  borderColor: '#ff1744'
};

function Drag(props) {
  const {
    getRootProps,
    getInputProps,
    isDragActive,
    isDragAccept,
    isDragReject,
    acceptedFiles
  } = useDropzone();

  const style = useMemo(() => ({
    ...baseStyle,
    ...(isDragActive ? activeStyle : {}),
    ...(isDragAccept ? acceptStyle : {}),
    ...(isDragReject ? rejectStyle : {})
  }), [
    isDragActive,
    isDragReject
  ]);
  const [data, setData] = useState(null)
  if(acceptedFiles.length === 1){
    const  readUploadedFileAsText = (acceptedFiles) => {
      const temporaryFileReader = new FileReader();      
      return new Promise((resolve, reject) => {
        temporaryFileReader.onerror = () => {
          temporaryFileReader.abort();
          reject(new DOMException("Problem parsing input file."));
        };

        temporaryFileReader.onload = () => {
          resolve(parser.fromSrt(temporaryFileReader.result));
        };
        temporaryFileReader.readAsText(acceptedFiles);
      });
    };
    let file = acceptedFiles[0]
    readUploadedFileAsText(file)
    .then(res => {
      setData({
        data: res
      })
    })
  } 

  return (
    <div className="container">
      <div {...getRootProps({style})}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>      
      <File file={data} />      
      {console.log(data)}
    </div>
  );
}

export default Drag

Let me know if I have to use any lifecycle methods. I tried using componentDidMount and componentWillReceiveProps but both didn't work for me or I hadn't done them in right way.

Take your readUploadedFileAsText function outside of the if statement it is in. Then you can add your if and function call to React.useEffect which will call the function on initial load, but not on every subsequent re-render.

function Drag(props) {
    const { getRootProps, getInputProps, isDragActive, isDragAccept, isDragReject, acceptedFiles } = useDropzone();

    const style = useMemo(
        () => ({
            ...baseStyle,
            ...(isDragActive ? activeStyle : {}),
            ...(isDragAccept ? acceptStyle : {}),
            ...(isDragReject ? rejectStyle : {})
        }),
        [isDragActive, isDragReject]
    );
    const [data, setData] = useState(null);

    const readUploadedFileAsText = acceptedFiles => {
        const temporaryFileReader = new FileReader();
        return new Promise((resolve, reject) => {
            temporaryFileReader.onerror = () => {
                temporaryFileReader.abort();
                reject(new DOMException('Problem parsing input file.'));
            };

            temporaryFileReader.onload = () => {
                resolve(parser.fromSrt(temporaryFileReader.result));
            };
            temporaryFileReader.readAsText(acceptedFiles);
        });
    };

    React.useEffect(() => {
        if (acceptedFiles.length === 1) {
            let file = acceptedFiles[0];
            readUploadedFileAsText(file).then(res => {
                setData({
                    data: res
                });
            });
        }
    }, [acceptedFiles]);


    return (
        <div className='container'>
            <div {...getRootProps({ style })}>
                <input {...getInputProps()} />
                <p>Drag 'n' drop some files here, or click to select files</p>
            </div>
            <File file={data} />
            {console.log(data)}
        </div>
    );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM