Trying Electron-React Boiler Plate Use #react-pdf/renderer to display PDF Component with PDFViewer Setup - react-pdf

Has anyone set up electron to pass the PDFViewer component that is then displayed to the DOM from React? I am able to display an empty box because the blob file and html aren't passed to the DOM like it does in a simple React app. The blob file is asked to be saved somewhere instead of just being used to the DOM as the simple React app does.
I thinking the PDFViewer information needs to be passed through the package.json/webpack somehow to the electron main.dev.ts file to properly display to the DOM.
I also get a memory leak due to PDFViewer being mounted and unmounted:
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
in InternalBlobProvider (created by PDFViewer)
in PDFViewer (at tearDownSummery.tsx:9)
in div (at tearDownSummery.tsx:8)
This is what I have to call my pdf component I setup that works up to the point to displaying to the DOM. The download link works and I get the PDF I structured through the .
import React from 'react';
import { PDFViewer, PDFDownloadLink } from '#react-pdf/renderer';
import ReactDOM from 'react-dom';
import TearDownPDF from './tearDowSummeryPDF';
export default function TearDownSummery() {
return (
<div>
<PDFViewer>
<TearDownPDF />
</PDFViewer>
<PDFDownloadLink document={<TearDownPDF />} fileName="IIR.pdf">
{({ blob, url, loading, error }) =>
loading ? <i> Loading document...</i> : <i> Download Pdf </i>}
</PDFDownloadLink>
</div>
);
}
ReactDOM.render(<TearDownSummery />, document.getElementById('root'));
Here is my GitHub project: https://github.com/staniszmatt/iir_Report.git
It is all set up on the pdfSetup branch.

Currently, Electron doesn't have the capability to use #react-pdf based off this post I found.
https://github.com/electron/electron/issues/13038
I'll have to come back to answer again if and when electron adds this capability.

Related

How to entirely disable server-side rendering in next.js v13?

The documentation says that I can disable server-side rendering by adding 'use client' to the top of files that need to be rendered only client-side.
However, in practice, I've added this header to every file in the project, and I see that both Layout and Page are being rendered server-side.
I can confirm this with a simple page:
'use client';
export default () => {
console.log('SERVER RENDER (page)');
return (
<div>test</div>
);
};
I would expect next dev to not output "SERVER RENDER (page)", but it does.
You don't need to disable server-side rendering (SSR), as it's not enabled by default in Next.js.
It pre-renders every page unless instructed otherwise, using either Static Generation or SSR.
Static Generation. The HTML generated at build time and will be reused at every request.
SSR. The HTML is generated on each request.
Next.js uses Static Generation whenever possible.
In your example, SSR doesn't happen. You're seeing the SERVER RENDER (page) message in terminal because you run it in dev (next dev) mode. In dev mode there is no build done, so the pages are generated on the go. You won't see this message in production mode. See this for more details.
Using use client; directive doesn't change the above, it just tells Next.js that a component is a Client Component, which will still be pre-rendered.
It looks like even if a component is marked 'use client', it will still be pre-rendered.
Client Components enable you to add client-side interactivity to your application. In Next.js, they are prerendered on the server and hydrated on the client. You can think of Client Components as how Next.js 12 and previous versions worked (i.e. the pages/ directory).
https://beta.nextjs.org/docs/rendering/server-and-client-components#client-components
#Nikolai pointed this out correctly, but did not answer how to disable SSR.
However, now that we know that Next 13 behaves the same as 12, we can also apply the same hydration workaround that was used in previous versions.
The TLDR is that you want to wrap your layout in a component that conditionally renders the element based on whether it detects the browser environment, e.g.
const Dynamic = ({ children }: { children: React.ReactNode }) => {
const [hasMounted, setHasMounted] = useState(false);
useEffect(() => {
setHasMounted(true);
}, []);
if (!hasMounted) {
return null;
}
return <>{children}</>;
};
export default ({ children }: { children: React.ReactNode }) => {
return (
<html lang="en">
<head />
<body>
<Dynamic>{children}</Dynamic>
</body>
</html>
);
};
Obviously, make sure you know what you are doing. This is generally not desired behavior, though there are exceptions.

Hybrid render with Next.js?

I'm new to Next.js and I'm using it to perform server side rendering on the landing page.
The landing page has: 1 generic component that's the same to every user and 1 component that is specific for each user.
Is it possible to perform server side rendering on the generic component, and client side rendering on the specific one?
Thank you.
Yes, you can do client-rendering for any component in your hierarchy. Client rendering usually means that when the component first renders, it fires off some asynchronous request for data (from an API, etc).
In your SSR page, just have your user-specific component not render anything on the initial render (except maybe some loading UI). Then include a useEffect hook that triggers the API call and sets state (local or global state as appropriate) which will trigger your component to re-render with the user-specific data.
During SSR, only the loading state will render. As soon as the component is mounted, the useEffect will trigger and the user-specific data will load and the component will re-render.
Overly simplistic example:
const UserGreeting = () => {
const [name, setName] = setState();
useEffect(() => {
getUserNameAsync().then((data) => {
setName(data.name);
})
}, [setName])
if (!name) {
return <div>...</div>
}
return (
<div>Welcome, {name}</div>
)
}
To make a page both dynamic and static at the same time is possible.
the solution for dynamic: you have to use react useState then useEffect to send the request after unloading fishing on the client side
but first must use next.js api getStaticProps() make the page static user's first visit

vuejs 3: inject key into child component?

Versions:
VueJS: 3.x
Chrome: Version 93.0.4577.63 (Official Build) (x86_64)
macOS: Big Sur 11.5.2
My use-case must be common, and I am mildly surprised that it does not work "out of the box".
I have these simple routes:
/patients/new
/patients/1
/about
which I access from a single-page application (SPA) through vueJS router-links:
<router-link to="/about">About</router-link> |
<router-link to="/patients/new">New Patient</router-link> |
<router-link to="/patients/1">Update Patient</router-link>
/patients/1 returns a pre-populated HTML FORM with details of patient with ID 1.
/patients/new returns the same HTML FORM with blank entries.
Intuitively, if I visit /patients/1 link, and then visit /patients/new, I would expect HTML FORM to be empty; conversely, if I visit /patients/new and then /patients/1, I would expect the HTML FORM to be pre-populated accordingly.
This is not what happens. Instead, the SPA does not re-create / re-mount the HTML FORM.
Solution: many articles suggest using a reactive variable referenced by a :key attribute in the HTML FORM. Then whichever link we visit, as long as we change the reactive variable, the vueJS component that houses the HTML FORM should be re-created / re-mounted.
My approach: provide a reactive variable at the root component, and inject it within the vueJS component (ie, the Patient component here) that renders the HTML FORM.
Here's what my root component looks like:
<script lang="ts">
import { defineComponent } from 'vue'
import Vue from 'vue'
export default defineComponent({
name: "App",
provide() {
return {
routePath: Vue.computed(() => this.$route.path)
}
}
});
</script>
where the reactive variable is routePath. Then in the Patient component, I have this:
export default defineComponent({
name: "Patient",
inject: ['routePath'],
...
});
with the HTML FORM defined with the :key attribute like this:
<template>
<form :key="routePath">
...
</form>
</template>
I believe the basic idea here is sound, but it is not working, and it does seem like a cumbersome approach.
So, here are my questions:
Is this approach sound?
Why is the Vue.computed() invocation broken? Here's the stack trace from Chrome console:
App.vue?3acc:9 Uncaught TypeError: Cannot read properties of undefined (reading 'computed')
at Proxy.provide (App.vue?3acc:9)
at qe (runtime-core.esm-bundler.js:2463)
at Pr (runtime-core.esm-bundler.js:6713)
at Lr (runtime-core.esm-bundler.js:6632)
at Tr (runtime-core.esm-bundler.js:6562)
at D (runtime-core.esm-bundler.js:4421)
at N (runtime-core.esm-bundler.js:4396)
at m (runtime-core.esm-bundler.js:3991)
at K (runtime-core.esm-bundler.js:5140)
at mount (runtime-core.esm-bundler.js:3477)
Thanks for looking into it.
It appears this issue is unresolved in vueJS 3.x. See open issue for details. There are work-arounds. Eg, see this github project. In my case, I've decided to change the workflow to avoid said issue.

next.js styles doesn't update on first render

Using next.js with SSR I'm having a strange problem.
My website renders as expected server-side and is served to the client with styles. There are no surprises here when I'm visiting the website on a laptop everything looks as expected.
However, when I visit the website on a mobile device (or simulated smaller window), the first render is rendered with the same styles as my desktop styles, even though my mobile media query returns true
I'm using https://github.com/wintercounter/use-breakpoint for most of my media queries.
Which looks like this:
const { 'isMobile-': isMobileMinus } = useBreakpoint()
and my layouts etc. should change based on whether isMobileMinus is true or false.
For example, this antD component is supposed to switch from horizontal to vertical if it's a mobile device.
<Space size="middle" direction={isMobileMinus ? 'vertical' : 'horizontal'}>
What is really interesting is that when I render the webpage in a small window the size of a mobile device I can console log isMobileMinus to be true, but my components do not update until I either resize the window (and it's true again) or I navigate to another page and back.
It acts as if isMobileMinus was false, but only for that specific component.
I can even render the value of isMobileMinus in the component and it will render true on first render, but the components I have acts as if it was false until I make another update.
I find this very strange as the component is clearly re-rendering with the correct value, but it does not update the styles of the components that were styled via SSR?
This problem is not just limited to the above hook based media queries but also other things.
For example I have 2 buttons that are rendered on SSR called "login" and "Signup" which are supposed to be white and green respectively.
However when the webpage renders if the user is already logged in. It should render 2 new buttons called "Log out" and "Dashboard" which are red and blue respectively.
But somehow on first render. The text of these buttons will update to logout and dashboard, but the styles of the buttons will be white and green (incorrect).
These are completely different components, but next.js still keeps the old styles?
if (loggedIn) {
return (
<Space>
<LogoutButton onClick={handleLogout} />
<DashboardButton onClick={handleDashboardClick} />
</Space>
)
}
return (
<Space>
<LoginButton />
<SignupButton onClick={showSignup} />
</Space>
)
There seems to be some really strange thing with next.js where it will update the content of the HTML, but refuses to update the CSS when a component is re-rendered on the client-side.
Anyone knows how to fix this?
I tried making a copy like suggested here: How to immediately re-render client-side using React + NextJS after initial server-side render? which seems to be a similar issue.
const breakpoints = useBreakpoint()
const copy = lodash.cloneDeep(breakpoints)
const { 'isMobile-': isMobileMinus } = copy
console.log('🔈 ~ isMobileMinus', isMobileMinus)
But that did not work for me either.
I'm on "next": "11.0.1",
I found 1 solution but it feels more like a hack than a solution.
If I wrap my components in process.browser && (<Component />) then the component will not render during SSR, and only render client-side.
This causes the component to render correctly when the webpage is loaded.
But of course I would ideally like to take advantage of SSR, and just update the styles client side :(
Note that this hack also causes console errors, so it is definitely not recommended. It seems like the use-breakpoint library is incompatible with SSR frameworks.

redux causing component re-rendering

I have a component which is connected to global store and getting some data from the global store. from some portion of this data is sent to another component via props and inside that component i have generated required jsx based on data. Also inside the child component mapdispatchtoprops is also used and it is also connected to global store as well.
The problem case scenario is child component re-renders depends upon the global store data.
The key for global store is like -
foods : {
'list' : '',
's' : '',
fetching : 0,
slist : '',
category : '',
cproducts : ''
}
I guess what happening is the child component is re-rendered 7 times because the number of keys inside global store for foods is 7. if anyone is interested he/she can share his/her views
Components have a render method which returns the JSX markup that it renders to the DOM. For change detection, React use a local state, which is only local to a component, when the state changes the component and its children are re-rendered to update the UI of the changed state.
A quote from the React documentation:
These components must not retain internal state, do not have backing instances, and do not have the component lifecycle methods. They are pure functional transforms of their input, with zero boilerplate. However, you may still specify .propTypes and .defaultProps by setting them as properties on the function, just as you would set them on an ES6 class.
PURE COMPONENT is one of the most significant ways to optimize React applications. The usage of Pure Component gives a considerable increase in performance because it reduces the number of render operation in the application.
So change your app to be like this
import React, {PureComponent} from 'react';
class Sample extends PureComponent {
render() {
return (
<div>your structure here</div>
)
}
}
export default Sample;
Please read more on react PureComponent. here

Resources