How to handle search, filters and product selection?
Unanswered
Tan posted this in #help-forum
TanOP
Hello I am making a fabric viewer in 3D but I don't understand how to split the components and fetch data dynamically when I select a new fabric.
the structure of the page is like this:
-- fabrics page
---- Viewer3D (yellow)
---- ProductDetails (blue)
---- ProductCatalog (green)
------ SearchInput
------ ProductFilters
Here are the features I would like to implement:
- Search
- Filter
- SelectProduct and view product details, 3d fabric and related products.
I cannot reload the filters page because the 3D viewer should be always ON and it will take some time to load if I reload every time.
It's basic interactivity but I'm a bit confused how to break things properly and make them communicate between them correctly. Could you give me some tips and point me to the right direction?
the structure of the page is like this:
-- fabrics page
---- Viewer3D (yellow)
---- ProductDetails (blue)
---- ProductCatalog (green)
------ SearchInput
------ ProductFilters
Here are the features I would like to implement:
- Search
- Filter
- SelectProduct and view product details, 3d fabric and related products.
I cannot reload the filters page because the 3D viewer should be always ON and it will take some time to load if I reload every time.
It's basic interactivity but I'm a bit confused how to break things properly and make them communicate between them correctly. Could you give me some tips and point me to the right direction?
1 Reply
If you're using
In my root layout (my app is full screen, so may need to be modified for yours)
This allows you to create a "view" anywhere on the page inline with your other HTML.
@react-three/fiber you can set it up so that the canvas persists between route changes. This way, you can load in your r3f as server components to keep your routing. I also use a package called tunnel-rat to help with this.In my root layout (my app is full screen, so may need to be modified for yours)
'use client'
import { useRef } from 'react'
import dynamic from 'next/dynamic'
const Scene = dynamic(() => import('./Scene'), { ssr: false })
const Layout = ({ children }) => {
const ref = useRef()
return (
<div
ref={ref}
style={{
position: 'relative',
width: ' 100%',
height: '100%',
overflow: 'auto',
touchAction: 'auto',
}}
>
{children}
<Scene
style={{
position: 'fixed',
top: 0,
left: 0,
width: '100vw',
height: '100vh',
pointerEvents: 'none',
}}
eventSource={ref}
eventPrefix='client'
/>
</div>
)
}
export { Layout }// Scene.jsx
"use client";
// This is used for the root layout. You probably want ./View.jsx instead
import { Canvas } from "@react-three/fiber";
import { Preload } from "@react-three/drei";
import { r3f } from "./global/rat";
export default function Scene({ ...props }) {
// Everything defined in here will persist between route changes, only children are swapped
return (
<Canvas {...props}>
{/* @ts-ignore */}
<r3f.Out />
<Preload all />
</Canvas>
);
}// ./global/rat.js
import tunnel from 'tunnel-rat'
export const r3f = tunnel()This allows you to create a "view" anywhere on the page inline with your other HTML.
// ./View.jsx
"use client";
import { forwardRef, Suspense, useImperativeHandle, useRef } from "react";
import { PerspectiveCamera, View as ViewImpl } from "@react-three/drei";
import { Three } from "./Three";
export const Common = ({ color }) => (
<Suspense fallback={null}>
{color && <color attach="background" args={[color]} />}
<ambientLight intensity={0.5} />
<pointLight position={[20, 30, 10]} intensity={1} />
<pointLight position={[-10, -10, -10]} color="blue" />
<PerspectiveCamera makeDefault fov={40} position={[0, 0, 6]} />
</Suspense>
);
const View = forwardRef(({ children, ...props }, ref) => {
const localRef = useRef(null);
useImperativeHandle(ref, () => localRef.current);
return (
<>
<div ref={localRef} {...props} />
<Three>
<ViewImpl track={localRef}>{children}</ViewImpl>
</Three>
</>
);
});
View.displayName = "View";
export { View };