react-filepond icon indicating copy to clipboard operation
react-filepond copied to clipboard

Flash of unstyled content (FOUC)

Open thomasjm opened this issue 4 years ago • 6 comments

Summary

The react-filepond component has a flash of unstyled content for me when it first comes up. This happens when I'm using React server-side rendering. It's happened for me when using both Gatsby.js and Next.js.

Here's a recording of me refreshing the page to show it:

filepond

How to reproduce

Just use the Filepond component in a SSR-ed app. I'm using it exactly like the example in this repo does. Here's a simplified version of my component:

import * as React from "react";

import "filepond/dist/filepond.min.css";
import { FilePond } from "react-filepond";

export default class MyComponent extends React.PureComponent {

  render() {
    return (
      <div>
          <FilePond allowMultiple={false}
                    onprocessfile={this.onProcessFile}
                    onprocessfilestart={this.onProcessFileStart}
                    beforeAddFile={this.beforeAddFile}
                    server={{
                      process: {
                        url: "/api/scratchpad/from_file",
                        method: "POST",
                        withCredentials: true,
                        headers: {},
                        onload: this.onLoad,
                        onerror: this.onError,
                        ondata: this.onData
                      }
                    }} />
      </div>
    );
  }
}

Expected behaviour

It should have the styled loaded before rendering the component so that there isn't a flicker.

Additional information

Environment Version
OS Linux
Device Laptop
Browser Chrome

thomasjm avatar Sep 03 '19 03:09 thomasjm

Maybe this is because it first checks for support and otherwise falls back to a file input?

rikschennink avatar Sep 05 '19 07:09 rikschennink

After looking at the code I was thinking it's actually because the rendering happens in this order:

  1. The component's render method creates a file input
  2. In componentDidMount the component calls the Filepond create method (see https://github.com/pqina/react-filepond/blob/master/lib/index.js#L53)

Thus the DOM has an unstyled input element in between these two things

thomasjm avatar Sep 05 '19 09:09 thomasjm

PR is welcome

rikschennink avatar Sep 09 '19 07:09 rikschennink

I thought about it a little but for my part I'm just going to work around this by moving it to a part of the UI where it isn't immediately visible. Here's my thoughts in case it helps someone else:

One option would be to hide the component until the Filepond create process is complete. But that would just create a delayed load of the component--better than a flicker, but not perfect.

A real solution would be to fully create the desired DOM element(s) in the React render method so it looks good when it is mounted. Maybe it's possible to render the Filepond into a detached DOM element and then convince React to render that (?). The alternative would be to actually render (parts of?) the Filepond UI using React.

thomasjm avatar Sep 09 '19 20:09 thomasjm

Has this been addressed yet?

rosman83 avatar Jun 15 '23 02:06 rosman83

i did sth like this :

export default function FileUpload({ chatId, addDocument }: FileUploadProps) { registerPlugin(FilePondPluginFileValidateType) registerPlugin(FilePondPluginFileValidateSize);

const [isVisible, setIsVisible] = useState(false);

useEffect(() => {
    const timer = setTimeout(() => {
        setIsVisible(true);
    }, 100);
    return () => clearTimeout(timer);
}, []);


return (
    <div>
        {isVisible && (
            <FilePond
                allowMultiple={false}
                credits={false}
                className={"w-64  mx-auto mt-8"}
                acceptedFileTypes={['application/pdf']}
                maxFileSize={'5MB'}
                allowRevert={false}
                server={
                    {
                        process: {
                            url: '/api/upload',
                            ondata: (data) => {
                                data.append('chat_id', chatId!);
                                return data;
                            },
                            onload: (response) => {
                                console.log(response);
                                const newDocument = JSON.parse(response);
                                addDocument(newDocument);
                                return response;
                            }
                        }
                    }
                }
            />
        )}
    </div>
);

}

xiaos avatar Oct 17 '23 09:10 xiaos