I am building a webpage using react-three-fiber and wanted to add subpages using the latest version of react-router dom. The problem is that I can't get the main page to work. Do I have to define the content, startup ... functions in separate pages in order to get the router to work instead of doing so in the App.js file?
My App.js:
import ReactDOM from "react-dom"
import React, { Suspense, useEffect, useRef, useMemo } from "react"
import { Canvas, Dom, useLoader, useFrame } from "react-three-fiber"
import { TextureLoader, LinearFilter } from "three"
import lerp from "lerp"
import { Text, MultilineText } from "./components/Text"
import Plane from "./components/Plane"
import { Block, useBlock } from "./blocks"
import state from "./store"
import About from "./About"
import { Router, Link, Route, Routes } from "react-router-dom";
import "./styles.css"
export function Startup() {
const ref = useRef()
useFrame(() => (ref.current.material.opacity = lerp(ref.current.material.opacity, 0, 0.025)))
return <Plane ref={ref} color="#0e0e0f" position={[0, 0, 200]} scale={[100, 100, 1]} />
}
export function Paragraph({ image, index, offset, factor, header, aspect, text, see, title }) {
const { contentMaxWidth: w, canvasWidth, margin, mobile } = useBlock()
const size = aspect < 1 && !mobile ? 0.65 : 0.9 //width of picture elements
const alignRight = (canvasWidth - w * size - margin) / 2
const pixelWidth = w * state.zoom * size
const left = (index)
const color = "#FFFFFF"
return (
<Block factor={factor} offset={offset}>
<group center>
<Plane map={image} args={[1, 1, 32, 32,]} shift={75} size={size} aspect={aspect} scale={[w * size, (w * size) / aspect, 1]} frustumCulled={false} />
<Dom
style={{ width: pixelWidth / (mobile ? 1 : 2), textAlign: left ? "left" : "right" }}
position={[left || mobile ? (-w * size) / 2 : 0, (-w * size) / 2 / aspect - 0.4, 1]}>
<div tabIndex={index}>{text}</div>
<a href={see}>{title}</a>
</Dom>
<Text center size={w * 0.04} color={color}>
{header}
</Text>
</group>
</Block>
)
}
export function Content() {
const images = useLoader(
TextureLoader,
state.paragraphs.map(({ image }) => image)
)
useMemo(() => images.forEach(texture => (texture.minFilter = LinearFilter)), [images])
const { contentMaxWidth: w, canvasWidth, canvasHeight, mobile } = useBlock()
return (
<>
<group rotation-z={0.025} rotation-y={0.0} rotation-x={0.05}>
<Block factor={1} offset={-0.1}>
</Block>
{state.paragraphs.map((props, index) => (
<Paragraph key={index} index={index} {...props} image={images[index]} />
))}
</group>
</>
)
}
export default function App() {
const scrollArea = useRef()
const onScroll = e => (state.top.current = e.target.scrollTop)
useEffect(() => void onScroll({ target: scrollArea.current }), [])
return (
<>
<Canvas className="canvas" concurrent pixelRatio={1} orthographic camera={{ zoom: state.zoom, position: [0, 0, 500] }}>
<Suspense fallback={<Dom center className="loading" children="Loading..." />}>
<Content />
<Routes>
<Route path="/about" element={<About />} />
</Routes>
<Startup />
</Suspense>
</Canvas>
<div className="scrollArea" ref={scrollArea} onScroll={onScroll}>
{new Array(state.sections).fill().map((_, index) => (
<div key={index} id={"0" + index} style={{ height: `${(state.pages / state.sections) * 30}vh` }} />//site length
))}
</div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
</li>
</ul>
</nav>
</>
);
}
And this is my index.js:
import "./styles.css"
import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import App from "./App";
import { render } from "react-dom";
const rootElement = document.getElementById("root");
render(
<BrowserRouter>
<App />
</BrowserRouter>,
rootElement
);