为什么父级中的 useEffect 状态更改没有发生在子级中?

问题描述 投票:0回答:1

下面是一个 FileUploader 组件(父组件),它在添加文件时呈现 ProgressBar(子组件)。我打算传入 FileReader onprogress,以便进度条的宽度从 0 到 100。为了测试,我制作了一个从 0 到 100 的 useEffect 计数器。我已经确认计数器状态正在通过 console.logging 计数器更新在 useEffect 中,但是 ProgressBar 组件中的进度状态并未更改,仅发送初始的 0。如何将计数器状态传递到 ProgressBar 子组件中,使其从 0 变为 100?

import { useState, useCallback, useEffect } from 'react'
import { useDropzone } from 'react-dropzone'

const ProgressBar = ({ exists, file, progress }) => {
  // only the first value, 0, of progress comes through, why not through 100?
  console.log(progress)
  return (
    <div className='progress-bar-component'>
      <div className='progress-bar-filename'>
        <span>{ file.name }</span>
      </div>
      <div className='progress-bar-group'>
        <div
          className={ `progress-bar${exists.length ? ' progress-bar-exists' : ''}` }
          style={ { width: `${progress}%` } }
        >
        </div>
        <div className='progress-bar-percent'>
          <span>{ exists.length ? 'Already uploaded' : `${progress}%` }</span>
        </div>
      </div>
    </div>
  )
}

const ProgressBars = ({ progressBars }) => {
  return (
    <div className='progress-bar-container'>
      {progressBars}
    </div>
  )
}

const FileUploader = () => {
  const [filesUploaded, setFilesUploaded] = useState([])
  const [progressBars, setProgressBars] = useState([])
  //
  const [counter, setCounter] = useState(0)
  const [start, setStart] = useState(false)
  useEffect(() => {
    if (start) {
      const timer = counter < 100 &&
      setInterval(() => {
        setCounter(counter + 1)
      }, 500)
      return () => clearInterval(timer)
    }
  }, [counter, start])
  //
  const onDrop = useCallback(acceptedFiles => {
    acceptedFiles.forEach(file => {
      const reader = new FileReader()

      reader.onloadstart = () => {
        return setFilesUploaded(filesUploaded => {
          return [...filesUploaded, file]
        })
      }
      reader.onabort = () => console.log('file reading was aborted')
      reader.onerror = () => console.log('file reading has failed')
      reader.onprogress = () => {
        setStart(true)
        return setProgressBars(progressBars => {
          return [
            ...progressBars,
            <ProgressBar
              key={progressBars.length}
              file={file}
              exists={filesUploaded}
              progress={counter}
            />
          ]
        })
      }
      reader.onload = () => {
        
      }
      reader.readAsArrayBuffer(file)
    })
    
  }, [filesUploaded, setStart, counter])

  const { getRootProps, getInputProps } = useDropzone({ onDrop, multiple: true })

  return (
    <div>
      <div className='file-uploader'>
        <div
          className='file-uploader-input'
          {...getRootProps()}
        >
          <input {...getInputProps()} />
          <p>Upload Files</p>
        </div>
      </div>
      <ProgressBars progressBars={progressBars} />
    </div>
  )
}

export default FileUploader
reactjs react-hooks
1个回答
1
投票

您在回调内部调用,并且 useEffect 不会影响该回调的渲染。尝试在回调之外调用,在父组件的返回部分

类似这样的:

return (
    <div>
      <div className='file-uploader'>
        <div
          className='file-uploader-input'
          {...getRootProps()}
        >
          <input {...getInputProps()} />
          <p>Upload Files</p>
        </div>
      </div>
      <ProgressBar
          key={progressBars.length}
          file={file}
          exists={filesUploaded}
          progress={counter}
        />
      <ProgressBars progressBars={progressBars} />
    </div>

© www.soinside.com 2019 - 2024. All rights reserved.