#3 Fix doesn't re-rerendering bug

Fixed a bug where re-rendering would not work when options and styles were changed.
main
NB 4 years ago
parent 73f2b9d98b
commit 7dae8d3fbe
  1. 22
      public/css/index.css
  2. 27
      src/index.tsx
  3. 190
      src/modules/epubViewer/EpubViewer.tsx
  4. 10
      src/modules/epubViewer/styles.ts
  5. 37
      src/modules/reactViewer/ReactViewer.tsx

@ -1,14 +1,14 @@
html, body { html,
padding: 0; body {
margin: 0; padding: 0;
} margin: 0;
width: 100vw;
html { height: 100vh;
width: 100vw;
height: 100vh;
} }
#root { #root {
width: 100%; height: 100%;
height: 100%; display: flex;
} align-items: center;
justify-content: center;
}

@ -1,20 +1,35 @@
import { useRef } from 'react' import { useRef } from 'react'
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import EpubViewer from 'modules/epubViewer/EpubViewer'
import ReactEpubViewer from 'modules/reactViewer/ReactViewer' import ReactEpubViewer from 'modules/reactViewer/ReactViewer'
import { ViewerRef } from 'types' import { ViewerRef } from 'types'
interface Props {
VIEWER_TYPE?: "ReactViewer" | "EpubViewer"
}
const App = () => { const App = ({ VIEWER_TYPE = "ReactViewer" }: Props) => {
const EPUB_URL = "/react-epub-viewer/files/Alices Adventures in Wonderland.epub"; const EPUB_URL = "/react-epub-viewer/files/Alices Adventures in Wonderland.epub";
const ref = useRef<ViewerRef>(null); const ref = useRef<ViewerRef>(null);
return ( return (
<ReactEpubViewer <>
url={EPUB_URL} {VIEWER_TYPE === "ReactViewer" && <>
ref={ref} <ReactEpubViewer
/> url={EPUB_URL}
ref={ref}
/>
</>
}
{VIEWER_TYPE === "EpubViewer" && <>
<EpubViewer
url={EPUB_URL}
ref={ref}
/>
</>
}
</>
); );
} }
ReactDOM.render(<App />, document.getElementById('root')); ReactDOM.render(<App />, document.getElementById('root'));

@ -53,84 +53,8 @@ const EpubViewer = ({
const [rendition, setRendition] = useState<Rendition | null>(null); const [rendition, setRendition] = useState<Rendition | null>(null);
const [toc, setToc] = useState<Toc[]>([]);
const currentCfi = useRef<string>(''); const currentCfi = useRef<string>('');
/**
* Init Book
* @method
* - Set book state
* - Set Epub path state
* - Set isLoaded state
* - Set toc state
*/
const initBook = () => {
if (book) {
book.destroy();
}
const book_ = new Book(url, epubFileOptions);
setBook(book_);
bookChanged && bookChanged(book_);
book_.loaded.navigation.then(({ toc }) => {
const toc_: Toc[] = toc.map(t => ({
label: t.label,
href: t.href
}));
setIsLoaded(true);
setToc(toc_);
tocChanged && tocChanged(toc_);
initRendition(book_);
});
// Init Location & Pagination
book_.ready.then(function() {
const stored = localStorage.getItem(book_.key() + '-locations');
if (stored) {
return book_.locations.load(stored);
} else {
return book_.locations.generate(1024);
}
}).then(() => {
localStorage.setItem(book_.key() + '-locations', book_.locations.save());
});
};
/**
* Init Rendition
* @method
* - Init iframe tag on DOM element
* - Set rendition
* - Set start page
*/
const initRendition = (book_: Book) => {
const node = ref.current;
if (!node || !book_) return;
const rendition_ = book_.renderTo(node, {
width: "100%",
height: "100%",
...epubOptions
});
setRendition(rendition_);
rendtionChanged && rendtionChanged(rendition_);
if(typeof location === "string") {
rendition_.display(location);
} else if(toc.length > 0 && toc[0].href) {
rendition_.display(toc[0].href);
} else {
rendition_.display();
}
}
/** /**
* Move page * Move page
* @method * @method
@ -238,20 +162,114 @@ const EpubViewer = ({
/** Ref checker */ /** Ref Checker */
useEffect(() => { useEffect(() => {
if (!ref) { if (!ref) {
throw new Error("[React-Epub-Viewer] Put a ref argument that has a ViewerRef type."); throw new Error("[React-Epub-Viewer] Put a ref argument that has a ViewerRef type.");
} }
}, [ref]); }, [ref]);
/** Epub Init */ /** Epub init options Changed */
/* eslint-disable */
useEffect(() => { useEffect(() => {
if (!url) return; if (!url) return;
initBook();
}, [url]); let mounted: boolean = true;
/* eslint-enable */ let book_: Book | any = null;
if (!mounted) return;
if (book_) {
book_.destroy();
}
book_ = new Book(url, epubFileOptions);
setBook(book_);
return () => {
mounted = false;
}
}, [url, epubFileOptions, setBook, setIsLoaded]);
/** Book Changed */
useEffect(() => {
if (!book) return;
if (bookChanged) bookChanged(book);
book.loaded.navigation.then(({ toc }) => {
const toc_: Toc[] = toc.map(t => ({
label: t.label,
href: t.href
}));
setIsLoaded(true);
if (tocChanged) tocChanged(toc_);
});
book.ready.then(function() {
if (!book) return;
const stored = localStorage.getItem(book.key() + '-locations');
if (stored) {
return book.locations.load(stored);
} else {
return book.locations.generate(1024);
}
}).then(() => {
if (!book) return;
localStorage.setItem(book.key() + '-locations', book.locations.save());
});
}, [book, bookChanged, tocChanged]);
/** Rendition Changed */
useEffect(() => {
if (!rendition) return;
if (rendtionChanged) rendtionChanged(rendition);
}, [rendition, rendtionChanged]);
/** Viewer Option Changed */
useEffect(() => {
let mounted = true;
if (!book) return;
const node = ref.current;
if (!node) return;
node.innerHTML = "";
book.ready.then(function() {
if (!mounted) return;
if (book.spine) {
const loc = book.rendition?.location?.start?.cfi;
// if (book.rendition) book.rendition.destroy();
const rendition_ = book.renderTo(node, {
width: "100%",
height: "100%",
...epubOptions
});
setRendition(rendition_);
if(loc) {
rendition_.display(loc)
} else {
rendition_.display();
}
}
});
return () => {
mounted = false;
}
}, [ref, book, epubOptions, style, setRendition]);
/** Location Changed */
useEffect(() => {
if (!ref.current || !location) return;
if (ref.current.setLocation) ref.current.setLocation(location);
}, [ref, location]);
/** /**
* Emit Viewer Event * Emit Viewer Event
@ -284,14 +302,6 @@ const EpubViewer = ({
]); ]);
/* eslint-enable */ /* eslint-enable */
/** Display page by changed location */
useEffect(() => {
if (!location || !rendition) return;
rendition.display(location);
}, [location, rendition]);
return (<> return (<>
{!isLoaded && loadingView} {!isLoaded && loadingView}
<div ref={ref} style={viewerStyle} /> <div ref={ref} style={viewerStyle} />

@ -3,10 +3,16 @@
*/ */
const styles: { const styles: {
boxSizing: any, boxSizing: any,
margin: any margin: any,
width: any,
height: any,
overflowY: any
} = { } = {
boxSizing: "border-box", boxSizing: "border-box",
margin: "0px auto" margin: "0px auto",
width: "100%",
height: "100%",
overflowY: 'hidden'
} }
export default styles export default styles

@ -50,14 +50,14 @@ const ReactViewer = ({
const [rendition, setRendition] = useState<Rendition | null>(null); const [rendition, setRendition] = useState<Rendition | null>(null);
const [layoutStyle, setLayoutStyle] = useState<Object>({}); const [layoutStyle, setLayoutStyle] = useState<{[key: string]: any}>({});
const [bookStyle, setBookStyle] = useState<BookStyle>({ const [bookStyle, setBookStyle] = useState<BookStyle>({
fontFamily: 'Origin', fontFamily: 'Origin',
fontSize: 18, fontSize: 16,
lineHeight: 1.4, lineHeight: 1.4,
marginHorizontal: 15, marginHorizontal: 0,
marginVertical: 5 marginVertical: 0
}); });
const [bookOption, setBookOption] = useState<BookOption>({ const [bookOption, setBookOption] = useState<BookOption>({
@ -71,8 +71,6 @@ const ReactViewer = ({
contents: null contents: null
}); });
/** /**
* Run book changed * Run book changed
* @method * @method
@ -118,17 +116,23 @@ const ReactViewer = ({
const h = bookOption.flow === "scrolled-doc" const h = bookOption.flow === "scrolled-doc"
? win_h - componentHeight ? win_h - componentHeight
: win_h - componentHeight - ~~((win_h - componentHeight - viewerLayout_.MIN_VIEWER_HEIGHT) / 100 * bookStyle.marginVertical); : win_h - componentHeight - ~~((win_h - componentHeight - viewerLayout_.MIN_VIEWER_HEIGHT) / 100 * bookStyle.marginVertical);
const marginTop = bookOption.flow === "scrolled-doc" const marginVertical = bookOption.flow === "scrolled-doc"
? "" ? ""
: `${~~((win_h - componentHeight - viewerLayout_.MIN_VIEWER_HEIGHT) / 100 * bookStyle.marginVertical) / 2}px`; : `${~~((win_h - componentHeight - viewerLayout_.MIN_VIEWER_HEIGHT) / 100 * bookStyle.marginVertical) / 2}px`;
setLayoutStyle(l => ({ setLayoutStyle(layout => {
...l, if (layout.width !== w || layout.height !== h || layout.marginTop !== marginVertical) {
width: w, return {
height: h, ...layout,
marginTop width: w,
})); height: h,
marginTop: marginVertical,
marginBottom: marginVertical
};
}
return layout;
});
try { try {
rendition.resize(w, h); rendition.resize(w, h);
} catch { } } catch { }
@ -212,8 +216,8 @@ const ReactViewer = ({
/** Set viewer Styles/Options */ /** Set viewer Styles/Options */
useEffect(() => { useEffect(() => {
viewerStyle && setBookStyle(viewerStyle); viewerStyle && setBookStyle(v => ({ ...v, ...viewerStyle }));
viewerOption && setBookOption(viewerOption); viewerOption && setBookOption(v => ({ ...v, ...viewerOption }));
}, [viewerStyle, viewerOption]); }, [viewerStyle, viewerOption]);
/** Apply viewer Styles/Options */ /** Apply viewer Styles/Options */
@ -277,7 +281,6 @@ const ReactViewer = ({
rendition.on("mouseup", onSelected); rendition.on("mouseup", onSelected);
return () => rendition.off("mouseup", onSelected); return () => rendition.off("mouseup", onSelected);
}, [rendition, onSelected]); }, [rendition, onSelected]);
return (<> return (<>

Loading…
Cancel
Save