Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions templates/nextjs-ts/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type { Metadata, Viewport } from "next";
import { LIFFProvider } from "../providers/liff-providers";

export const metadata: Metadata = {
title: "LIFF App",
icons: {
icon: "/favicon.ico",
},
};

export const viewport: Viewport = {
width: "device-width",
initialScale: 1.0,
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="jp">
<body>
<LIFFProvider>{children}</LIFFProvider>
</body>
</html>
);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import Head from "next/head";
import styles from "../styles/Home.module.css";
"use client";
import { useLIFF } from "../providers/liff-providers";
import styles from "../styles/App.module.css";

export default function Home() {
const { liff, liffError } = useLIFF();

export default function Home({ liff, liffError }) {
return (
<div>
<Head>
<title>LIFF App</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
</Head>

<main className={styles.main}>
<h1>create-liff-app</h1>
{liff && <p>LIFF init succeeded.</p>}
Expand Down
37 changes: 0 additions & 37 deletions templates/nextjs-ts/pages/_app.tsx

This file was deleted.

62 changes: 62 additions & 0 deletions templates/nextjs-ts/providers/liff-providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
"use client";

import { Liff } from "@line/liff";
import { createContext, useContext, useEffect, useState } from "react";

interface LIFFContextValue {
liff: Liff | null;
isLoading: boolean;
liffError: string | null;
}

const LIFFContext = createContext<LIFFContextValue>({
liff: null,
isLoading: true,
liffError: null,
});

function LIFFProvider({ children }: { children: React.ReactNode }) {
const [liffObject, setLiffObject] = useState<Liff | null>(null);
const [liffError, setLiffError] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);

// Execute liff.init() when the app is initialized
useEffect(() => {
// to avoid `window is not defined` error
import("@line/liff")
.then((liff) => liff.default)
.then((liff) => {
console.log("LIFF init...");
liff
.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID! })
.then(() => {
console.log("LIFF init succeeded.");
setLiffObject(liff);
})
.catch((error: Error) => {
console.log("LIFF init failed.");
setLiffError(error.toString());
})
.finally(() => {
setIsLoading(false);
});
});
}, []);

const value: LIFFContextValue = {
liff: liffObject,
isLoading,
liffError: liffError,
};
return <LIFFContext.Provider value={value}>{children}</LIFFContext.Provider>;
}

function useLIFF(): LIFFContextValue {
const liff = useContext(LIFFContext);
if (!liff) {
throw new Error("useLIFF must be used within a LIFFProvider");
}
return liff;
}

export { LIFFProvider, useLIFF };
23 changes: 23 additions & 0 deletions templates/nextjs/app/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { LIFFProvider } from "../providers/liff-providers";

export const metadata = {
title: "LIFF App",
icons: {
icon: "/favicon.ico",
},
};

export const viewport = {
width: "device-width",
initialScale: 1.0,
};

export default function RootLayout({ children }) {
return (
<html lang="jp">
<body>
<LIFFProvider>{children}</LIFFProvider>
</body>
</html>
);
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import type { Liff } from "@line/liff";
import type { NextPage } from "next";
import Head from "next/head";
import styles from "../styles/Home.module.css";
"use client";
import { useLIFF } from "../providers/liff-providers";
import styles from "../styles/App.module.css";

export default function Home() {
const { liff, liffError } = useLIFF();

const Home: NextPage<{ liff: Liff | null; liffError: string | null }> = ({
liff,
liffError
}) => {
return (
<div>
<Head>
<title>LIFF App</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" href="/favicon.ico" />
</Head>

<main className={styles.main}>
<h1>create-liff-app</h1>
{liff && <p>LIFF init succeeded.</p>}
Expand All @@ -36,6 +28,4 @@ const Home: NextPage<{ liff: Liff | null; liffError: string | null }> = ({
</main>
</div>
);
};

export default Home;
}
Empty file.
33 changes: 0 additions & 33 deletions templates/nextjs/pages/_app.js

This file was deleted.

61 changes: 61 additions & 0 deletions templates/nextjs/providers/liff-providers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"use client";

import React, { createContext, useContext, useEffect, useState } from "react";

const LIFFContext = createContext({
liff: null,
liffError: null,
});

function LIFFProvider({ children }) {
const [liffObject, setLiffObject] = useState(null);
const [liffError, setLiffError] = useState(null);

// 在组件挂载时执行 liff.init()
useEffect(() => {
// 动态导入 @line/liff,以避免在 Next.js 服务端渲染时出现 window is not defined 的错误
import("@line/liff")
.then((liff) => liff.default)
.then((liff) => {
console.log("LIFF init...");
const liffId = process.env.NEXT_PUBLIC_LIFF_ID;
if (!liffId) {
throw new Error("NEXT_PUBLIC_LIFF_ID is not defined.");
}

liff
.init({ liffId: liffId })
.then(() => {
console.log("LIFF init succeeded.");
setLiffObject(liff);
})
.catch((error) => {
console.log("LIFF init failed.");
setLiffError(error.toString());
});
})
.catch((error) => {
console.log("LIFF init failed.");
setLiffError(error.toString());
});
}, []);

const value = {
liff: liffObject,
liffError: liffError,
};

return <LIFFContext.Provider value={value}>{children}</LIFFContext.Provider>;
}

function useLIFF() {
const context = useContext(LIFFContext);

if (context === undefined) {
throw new Error("useLIFF must be used within a LIFFProvider");
}

return context;
}

export { LIFFProvider, useLIFF };