mirror of
https://github.com/lockin-bot/react-telegram.git
synced 2026-05-14 16:59:23 +08:00
feat: add React Router example with MemoryRouter
- Install react-router-dom dependency - Create react-router-experiment.tsx demonstrating React Router usage - Implement navigation with Routes, nested routes, and navigation hooks - Add example pages: Homepage, BlogsIndex, and BlogPage with params - Use MemoryRouter for in-memory routing suitable for Telegram bots 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
11
bun.lock
11
bun.lock
@@ -33,6 +33,7 @@
|
||||
"@react-telegram/core": "workspace:*",
|
||||
"@react-telegram/mtcute-adapter": "workspace:*",
|
||||
"react": "^19.1.0",
|
||||
"react-router-dom": "^7.6.3",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "npm:pure-react-types@^0.1.4",
|
||||
@@ -166,6 +167,8 @@
|
||||
|
||||
"ci-info": ["ci-info@3.9.0", "", {}, "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ=="],
|
||||
|
||||
"cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"detect-indent": ["detect-indent@6.1.0", "", {}, "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA=="],
|
||||
@@ -278,8 +281,14 @@
|
||||
|
||||
"react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="],
|
||||
|
||||
"react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="],
|
||||
|
||||
"react-reconciler": ["react-reconciler@0.32.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-2NPMOzgTlG0ZWdIf3qG+dcbLSoAc/uLfOwckc3ofy5sSK0pLJqnQLpUFxvGcN2rlXSjnVtGeeFLNimCQEj5gOQ=="],
|
||||
|
||||
"react-router": ["react-router@7.6.3", "", { "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" }, "optionalPeers": ["react-dom"] }, "sha512-zf45LZp5skDC6I3jDLXQUu0u26jtuP4lEGbc7BbdyxenBN1vJSTA18czM2D+h5qyMBuMrD+9uB+mU37HIoKGRA=="],
|
||||
|
||||
"react-router-dom": ["react-router-dom@7.6.3", "", { "dependencies": { "react-router": "7.6.3" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-DiWJm9qdUAmiJrVWaeJdu4TKu13+iB/8IEi0EW/XgaHCjW/vWGrwzup0GVvaMteuZjKnh5bEvJP/K0MDnzawHw=="],
|
||||
|
||||
"read-yaml-file": ["read-yaml-file@1.1.0", "", { "dependencies": { "graceful-fs": "^4.1.5", "js-yaml": "^3.6.1", "pify": "^4.0.1", "strip-bom": "^3.0.0" } }, "sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA=="],
|
||||
|
||||
"resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
|
||||
@@ -294,6 +303,8 @@
|
||||
|
||||
"semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="],
|
||||
|
||||
"set-cookie-parser": ["set-cookie-parser@2.7.1", "", {}, "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
"dependencies": {
|
||||
"@react-telegram/core": "workspace:*",
|
||||
"@react-telegram/mtcute-adapter": "workspace:*",
|
||||
"react": "^19.1.0"
|
||||
"react": "^19.1.0",
|
||||
"react-router-dom": "^7.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "npm:pure-react-types@^0.1.4",
|
||||
|
||||
138
packages/examples/src/react-router-experiment.tsx
Normal file
138
packages/examples/src/react-router-experiment.tsx
Normal file
@@ -0,0 +1,138 @@
|
||||
/// <reference types="@react-telegram/core" />
|
||||
|
||||
import React, { PropsWithChildren } from "react";
|
||||
import { MemoryRouter, Outlet, Route, Routes, To, useLocation, useNavigate, useParams } from "react-router-dom";
|
||||
import { MtcuteAdapter } from "@react-telegram/mtcute-adapter";
|
||||
|
||||
export const ReactRouterExperiment = () => {
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<Routes>
|
||||
<Route element={<Layout />}>
|
||||
<Route index element={<Homepage />} />
|
||||
<Route path="blogs" element={<BlogsIndex />} />
|
||||
<Route path="blogs/:id" element={<BlogPage />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</MemoryRouter>
|
||||
);
|
||||
};
|
||||
|
||||
export const Layout = () => {
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<i>path: {location.pathname}</i>
|
||||
<br />
|
||||
<br />
|
||||
<Outlet />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const BackButton = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<button onClick={() => navigate(-1)}>
|
||||
⬅️ Back
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export const NavigateButton = ({
|
||||
to,
|
||||
children,
|
||||
}: PropsWithChildren<{
|
||||
to: To
|
||||
}>) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<button onClick={() => navigate(to)}>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
export const Homepage = () => {
|
||||
return (
|
||||
<>
|
||||
<b>This is the homepage</b>
|
||||
<br />
|
||||
<br />
|
||||
<row>
|
||||
<NavigateButton to="/blogs">
|
||||
📝 Blogs
|
||||
</NavigateButton>
|
||||
</row>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const BlogsIndex = () => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<>
|
||||
<row>
|
||||
<BackButton />
|
||||
</row>
|
||||
<br />
|
||||
<b>Please select a post :3</b>
|
||||
<br />
|
||||
<br />
|
||||
<row>
|
||||
<button onClick={() => navigate(`/blogs/0`)}>Post 0</button>
|
||||
<button onClick={() => navigate(`/blogs/1`)}>Post 1</button>
|
||||
</row>
|
||||
<row>
|
||||
<button onClick={() => navigate(`/blogs/2`)}>Post 2</button>
|
||||
<button onClick={() => navigate(`/blogs/3`)}>Post 3</button>
|
||||
</row>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const BlogPage = () => {
|
||||
const { id = "unknown" } = useParams();
|
||||
|
||||
return (
|
||||
<>
|
||||
<row>
|
||||
<BackButton />
|
||||
</row>
|
||||
<br />
|
||||
<b>Blog page for: {id}</b>
|
||||
<br />
|
||||
<br />
|
||||
<i>This is the content for blog post #{id}</i>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
// Bot setup
|
||||
async function main() {
|
||||
const config = {
|
||||
apiId: parseInt(process.env.API_ID || '0'),
|
||||
apiHash: process.env.API_HASH || '',
|
||||
botToken: process.env.BOT_TOKEN || '',
|
||||
storage: process.env.STORAGE_PATH || '.mtcute'
|
||||
};
|
||||
|
||||
if (!config.apiId || !config.apiHash || !config.botToken) {
|
||||
console.error('Please set API_ID, API_HASH, and BOT_TOKEN environment variables');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const adapter = new MtcuteAdapter(config);
|
||||
|
||||
adapter.onCommand('router', () => <ReactRouterExperiment />);
|
||||
|
||||
await adapter.start(config.botToken);
|
||||
|
||||
console.log('Bot is running! Send /router to see React Router example.');
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
Reference in New Issue
Block a user