0

I am using react-file-viewer in React.js app to read docx. I use a template code. I can read the file, but as soon as I dynamically change the filePath - FileViewer does not reload. I can see that my component gets updated with a new filePath, and I can render a new filePath in a container code, so it gets displayed on screen, but the actual FileViewer does not re-render and displays previously loaded document.

5 Answers 5

3

You should wrap the file viewer component with a div and provide a key which can be a random number:

return(
    <div key={Math.random()}>
        <FileViewer
            fileType={filetype}
            filePath={path}
            etc.
        />
    </div>
)
Sign up to request clarification or add additional context in comments.

Comments

1

Managed to get it working by forcing unmounting of the container that wraps <File Viewer /> as on initial mount the document was loading properly and the only time it was not working was on a re-render. To unmount, I used a key attribute as described here by T.J. Crowder.

// Parent.js
return (
    <div>
        {this.state.filePath && <FileViewerWrapper filePath={this.state.filePath} />}
    <div>
);

// Child.js
render(){
    ++this.childKey; // initialized in constructor
    return (
        <FileViewer
            fileType='docx'
            filePath={path.resolve(__dirname), `path/${this.props.filePath}`}
            etc.
        />
    );
}

As from the linked answer -

The child will have a new key each time, so React will assume it's part of a list and throw away the old one, creating the new one. Any state change in your component that causes it to re-render will force that unmount-and-recreated behavior on the child.

P.S. Initially I tried to use unmountComponentAtNode method from ReactDOM with a ref on a Child component. Something like this -

  let mountNode = ReactDOM.findDOMNode(this.refs.mount);

  try {
    ReactDOM.unmountComponentAtNode(mountNode);
  } catch (e) {
    console.error(e);
  }

but was getting a warning unmountComponentAtNode(): The node you're attempting to unmount was rendered by React and is not a top-level container. Instead, have the parent component update its state and rerender in order to remove this component. So, the solution with key works for me better.

Comments

1

Hi I had the same issue and I managed to fix it by adding a dynamic key to the FileViewer: This will rerender the component each times the filePath changes.

<FileViewer
        key={this.props.filePath}
        fileType='docx'
        filePath={path.resolve(__dirname), `path/${this.props.filePath}`}
        etc.
/>

Comments

1

make sure to pass unique key if u have multiple documents you want to display.

something like

const FileViewerComponent = (props) => {

const [state, setState] = useState({
    type: getFileExtension(props.file.Title),
    path: getFilePath(props.file.Path)
});
useEffect(() => {
    if (state.path != getFilePath(props.file.Path)) {
        setState({
            type: getFileExtension(props.file.Title),
            path: getFilePath(props.file.Path)
        })
    }
});

return (<div style={{maxHeight: '700px', 'overflow-y': 'scroll'}}>
        <FileViewer 
          fileType={state.type} 
          filePath={state.path} 
          key= {state.path}
       />
    </div>
);

};

Comments

0

In your dynamically change filepath event you can make your file path empty then set the new file path.

 constructor() {
      this.state = {      
      filePreviewPath: "",
      filePreviewType: "",
    };
  }


// dynamic load event           
    this.setState({           
      filePreviewPath: "",
      filePreviewType: ""
    });

    this.setState({
      filePreviewPath: filePathDataUrl, // filePathDataUrl: string = "data:" + mimeTypeforPreview + ";base64, " + fileObj.fileContent;
      filePreviewType: filePreviewType  // filePreviewType = "pdf"
    });

html

<FileViewer
  fileType={this.state.filePreviewType}
  filePath={this.state.filePreviewPath}
/>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.