Home  >  Q&A  >  body text

Sequence of rerendering and useEffect() calls

I have components TopPage and ImagePreview and FileUploader

  1. Display first FileUploader,

  2. FileUploader changes the fileObj state of TopPage.

  3. Then, FileUploader disappeared, ImagePreview appeared, and useEffect() was called at the same time, but there was no ImagePreviewRef at this time.

When useState is called, both component re-rendering and useEffect will be called.

The command is useEffect ->re-render?

If so, how can I solve this problem?

const TopPage = (props) =>{
    const [fileObj, setFileObj ] = useState();
    const imagePreviewRef = useRef();
    useEffect(() =>{
        console.log("useEffect() is called with fileObj:",fileObj);
        console.log("imagePrevireRef.current is ready?",imagePreviewRef.current);
        imagePreviewRef.current.loadPic(fileObj);
    },[fileObj]);

    if (fileObj){
      return <ImagePreview ref={imagePreviewRef}></ImagePreview>
    }
    else {
      return <FileUploader SetFileObj=setFileObj></FileUploader>
    }
}

const FileUploader = (props) => {
   // props.setFileObj() is called here.
}
const ImagePreview = (props) => {
   const loadPic = () =>{// loadpicture to canvas }   
}

Temporary solution,

I do like this so far, Rendering ImagePreview and FileUploader Components are toggled from the beginning via display:none.

Looks a bit awkward...but works great so far.

const TopPage = (props) =>{
    const [fileObj, setFileObj ] = useState();
    const imagePreviewRef = useRef();
    useEffect(() =>{
        console.log("useEffect() is called with fileObj:",fileObj);
        console.log("imagePrevireRef.current is ready?",imagePreviewRef.current);
        imagePreviewRef.current.loadPic(fileObj);
    },[fileObj]);

    if (fileObj){
      return 
<React.Fragment>
<div style={{display:"block"}}>
<ImagePreview ref={imagePreviewRef}></ImagePreview>
</div>
<div style={{display:"none"}}>
<FileUploader SetFileObj=setFileObj></FileUploader>
</div>
</React.Fragment>
    }
    else {
      return 
<React.Fragment>
<div style={{display:"none"}}>
<FileUploader SetFileObj=setFileObj></FileUploader>
</div>
<div style={{display:"block"}}>
<ImagePreview ref={imagePreviewRef}></ImagePreview>
</div>
</React.Fragment>
    }
}

const FileUploader = (props) => {
   // props.setFileObj() is called here.
}
const ImagePreview = (props) => {
   const loadPic = () =>{// loadpicture to canvas }   
}

P粉722409996P粉722409996234 days ago393

reply all(1)I'll reply

  • P粉165522886

    P粉1655228862024-03-23 00:36:53

    Render uniformly, then use CSS to conditionally display the component to preserve the reference.

    const TopPage = (props) =>{
        const [fileObj, setFileObj ] = useState();
        const imagePreviewRef = useRef();
        useEffect(() =>{
           if(imagePreviewRef.current)
            imagePreviewRef.current.loadPic(fileObj);
        },[fileObj]);
    
        return (
          <> 
           
    {fileObj && } ) }

    reply
    0
  • Cancelreply