How to create a layout.js file in Next.js 13 if I use React Context providers? - next.js

In Nextjs 13 there is a reference to creating a layout.js file that replaces the app and document files, but they state that If you are using any React Context providers, they will need to be moved to a Client Component.
What does that mean exactly? The files should not be upgraded or you should mark 'use client' in the layout.js file?

next-13 app directory rendered on the server by default. Context api is used on client side. You do not have to use app directory. you can still use pages directory and wrap the app with Context Provider. But this approach is very expensive and cause to many unnecessary rerenders when the context value changes.
Looks like in next-13, will layout.js file, we are going to break the application state into smaller chunks.
Layouts: Easily share UI between routes while preserving state and
avoiding expensive re-renders.
Imagine you have blogs and 'dashboarddirectories insideappdirectory. In eachlayout.js`, you can fetch data, create some state and pass them to its own children via the prop drilling. In that way, we will kinda have a modular state. new layout system will avoid unnecessary re-renders.
Imagine your app was wrapped by ContextProvider and [slug] component was causing a state change in the ContextProvider, so your entire app will be rerendering. but if you keep the top level data for [slug] component inside blog layout, state change in layout will only rerender this layput's children components
If you want to opt out server component and choose to use use client directive, you can use createContext and this time each tree will have their own context

Related

How to use `getServerSideProps` in persistent layouts shared by multiple pages in Next.js?

I have shared layouts for several logical groups of pages, for example:
DashboardLayout:
/dashboard/foo
/dashboard/bar
UserLayout:
/user/settings
/user/profile
Both DashboardLayout and UserLayout use data that has to be fetched on the server-side (e.g. from a database server).
How can I:
fetch this data from the layout components when getServerSideProps only works in page components; and
keep the fetching logic tied to the layouts and not the page components or the App component; and
keep the layouts persistent (Next.js docs), i.e. prevent re-fetching/re-rendering when navigating between pages using the same layout (e.g. from /user/settings to /user/profile); and
ideally not use any third-party libraries nor shallow routing?

Modification to published magnolia components

Let suppose that in Magnolia's Page application you have few pages with instances of component "A" which have property dialog. These pages are published to Public server.
later you decide to change structure of this properties (add fields or for example change image field to array of images)
to do so you would modify component's dialog yaml file (add/modify fields) and component's template ftl file to render these changes
Question: - will this destroy previously created pages with instances of component "A"? i.e. if you need to modify component's properties it's better to create new component instead of modify existing?
It's fine to modify existing component, as long as you take care of the fact that existing instances will not have any values for newly added properties/fields. So in template you need to expect that you might get empty values and provide good defaults to cover that case. So technically, you can modify the component just fine.
Whether it is better to create new component or modify existing one depends more on the business needs. Is it desired pages to see new component look & get new fields in pages that already use the component or are those changes relevant just for new pages in which component will be used?
Another consideration is the more components you have, the harder it would be for editor to pick the right one from the ever growing list. However the more functionality you cram into single component, the more complex and difficult to test it would become and harder it would be to replace it with something else in the future.

How can I encapsulate svelte app within iframe of svelte app?

A svelte app targeted for mobile will be emulated online (a mobile drawing with the actual app rendered inside). Because of media queries (which don't work since the app is the whole page and not just the mobile drawing content), my best solution would be that the app should be inside of an iframe.
Is there a way of doing that without actually writing another svelte app that encapsulates the former? Since it will bundle everything together. I could deal with sapper settings to control that, but it seems a little messy to me. As is distorting CSS to emulate media queries, toggling all back when released to production target.
I would then be running two diferent sapper CLI's dev servers, package.json's, git repos, etc. Also have to think about deploy, regarding two public/dist folders and their paths/routes.
Any other thoughts?
EDIT: to be more clear, I have essentially 4 options:
1 - adapt CSS without media queries and vh/vw units (way to hard and sometimes maybe impossible)
2 - emulator as component (but where would iframe src point to?)
3 - set two rollup outputs, maybe app is a hydratable component. Iframe would point to output 2 (how to coordinate that? index1 vs index2? same public folder with 2 rendered parts of an app)
4 - two independent apps, the whole thing (how to deploy? two webservers could do, but ideally it should become one final app)
Hope it is clearer
You can use just select the target to be iframe body. More info about how to create a svelte component https://svelte.dev/docs#Client-side_component_API
import App from './App.svelte';
const iframe = document.createElement("iframe");
iframe.onload = (ev) => {
const app = new App({
target: iframe.contentWindow.document.body,
props: {
name: 'world'
}
});
};
document.body.append(iframe);
if I got you right.
how about packing into a scrollable div?
your svelte app is packaged into a bundle.js. Rename index.html to sth.html and then iframe src=sth.html in the new index.html

Next.js use of _app.js and _document.js

I currently use _document.js to inject css into my Next.js app and I would like to start using _app.js to help inject data into pages.
Was wondering if it possible to use _document and _app in tandem or should we only use one or the other?
Short answer: Yes, You can use both. They serve different purpose and can be used in the same application.
According to NextJS docs:
Next.js uses the App component to initialize pages.
To override, create the ./pages/_app.js file and override the App class
and
Pages in Next.js skip the definition of the surrounding document's markup. For example, you never include <html>, <body>, etc. To override that default behavior, you must create a file at ./pages/_document.js, where you can extend the Document class.
Note: _document.js is only rendered on the server side and not on the client side. so event handlers like onClick is not going to work.

Using Angular 2 components on existing ASP.NET web pages

I am trying to move the front-end part of a website to Angular 2.
Currently I have really big ASP.NET 4.5 website.
I would like to create a separated Angular 2 project as it will be growing with time (and hopefully replace the asp.net)
For now I would like to create this project in Visual Studio (2015) and use some angular components or modules in the actual ASP.NET website.
Does the angular AppModule as to be in the ASP website?
I made some research but could not find answers or examples.
Am I gonna be able to do this relying on npm and system.js ? I saw that a lot of people are using gulp for copying file.
Is there a "right" way of doing this?
Any help would be highly appreciated
This question is not specific to Visual Studio, but yes, you can certainly accomplish this.
As you have suggested you can and should maintain the Angular application as a separate project.
The only additions that you need to make to your .aspx page are
including SystemJS and its configuration via script tags in that page or in its Master Page (You can also do this dynamically for CMS pages and using all sorts of other strategies). For example
<script src="loction-of-systemjs.js"></script>
<script src="loction-of-systemjs.config.js"></script>
Adding a markup tag with the selector corresponding to the app's root element, say 'my-embeddedable-widget', to your .aspx markup. For example
<my-embeddedable-widget>Loading...</my-embeddedable-widget>
Importing your application via SystemJS.import from a script tag embedded in the page containing the component selector above. For example
<script>
SystemJS.import('my-embeddedable-widget')
.catch (function(e) {
console.error(e);
}); // not using .bind or => here since aspx tends to imply older browser support
</script>
Note that this presupposes two things
that the 'my-embeddedable-widget' is set up in your SystemJS configuration. For example
SystemJS.config({
packages: {
'my-embeddedable-widget': {
main: 'main.ts' // just an example, could be main.js or anything really
}
}
});
If it is not you can add the config entry above as appropriate for your app (strongly recommended) or just import it directly from the path to the app's entry point such as e.g. my-embeddedable-widget/main.ts or my-embeddedable-widget/main.js.
That the entry point of your widget declares all of its platform level dependencies, such as zone.js and likely various polyfills. For example
my-embeddedable-widget/main.ts
import 'zone.js';
import 'core-js';
// ...
import {platformBrowserDynamic} from '#angular/platform-browser-dynamic';
// ....
This means that SystemJS will automatically load them when your widget is requested. While you could bring them in via separate script tags as we do with the loader itself, making them explicit dependencies of our widget by using ES Modules improves maintainability and allows us to defer loading them until they are required. Furthermore it helps further decouple the widget from the .aspx page. However, if other JavaScript on the page requires these polyfills, you may need to adjust this approach (especially with respect to zone.js because it monkey patches window.Promise)

Resources