Search code examples
javascriptreactjsuse-contextreact-three-fiber

Theme colors won't load/update correctly using useContext hook in combination with three.js (react-three-fiber) component


Could someone tell me why all the components in the <ThemeContext.Provider> tags adapt when changing the theme, but the three.js components (<Box/> and <Cube/>) don't?

Box.jsx:

import { useFrame, useThree } from "@react-three/fiber";
import React, { useContext, useEffect } from "react";
import { useRef } from "react";
import { angleToRadians } from "../../../utils/angle";
import * as THREE from "three";
import { themes, ThemeContext } from "../../../utils/Theme";

export default function Box(){
   
    const orbitControlsRef = useRef(null);
    useFrame((state) => {
        if (orbitControlsRef.current) {
            const { x, y } = state.mouse;
            orbitControlsRef.current.setAzimuthalAngle(-x * angleToRadians(45));
            orbitControlsRef.current.setPolarAngle((y+ 1.5) * angleToRadians(90 - 30));
            orbitControlsRef.current.update();
        }

    })
const q = window.innerWidth;
const canvas = document.querySelector('.canvas');
var deviceAngle = 0;
if(window.matchMedia("(pointer: coarse)").matches) {
    canvas.setAttribute('style', 'pointer-events: none;');
    deviceAngle = 50;
}
else{
    deviceAngle = 160;

}
const theme = useContext(ThemeContext);


    return (
        <>
         <PerspectiveCamera makeDefault position={[0, 0, 7]} fov={90} />
              <OrbitControls ref={orbitControlsRef} minPolarAngle={angleToRadians(20)} maxPolarAngle={angleToRadians(deviceAngle)} enableDamping enabled={false}/>

           
        {/* <OrbitControls /> */}
        <mesh position={[0,0,0]} rotation={[0,0,0]}>
            <torusBufferGeometry attach={'geometry'} args={[5,2,70,100]} />
            <MeshDistortMaterial
            wireframeLinecap wireframeLinejoin 
            attach="material" 
            wireframe
            speed={0.4}
            distort={0.46}
            color={theme.pLight}/>
        </mesh>
        <fog attach="fog" color={theme.secondary} near={5} far={7.5} position={[0,0,0]}/>
        <mesh position={[0,0,0]}>
        <pointLight color={theme.cta} intensity={0.3} position={[0,0,1]} />
        <ambientLight color={theme.secondary} intensity={0.5} />
        </mesh>
        </>
    )
} 
`

App.jsx:

Here I import a theme object containing themes within it, and setting the ThemeContext to the current theme. This happens at the comment line marked with -+-.

import Box from "./components/three/box/Box";
import { Html, useProgress} from "@react-three/drei"
import { Canvas } from "@react-three/fiber"
import Cursor from "./components/cursor/Cursor";
import Welcome from "./components/welcome/Welcome";
import Socials from "./components/socials/Socials";
import Scroll from "./components/scroll_indicator/Scroll";
import About from "./components/about/About";
import { OrbitControls } from "@react-three/drei";
import {
  EffectComposer,
  Bloom,
  Glitch,
  Scanline
} from "@react-three/postprocessing";
import { BlendFunction, Resizer, KernelSize, GlitchMode } from 'postprocessing'
import Section from "./components/ux/section/Section";
import { Suspense, createContext, useContext } from "react";
import BottomBar from "./components/ux/bottom_bar/BottomBar";
import ProgressBar from "./components/ux/progress_bar/ProgressBar";
import Skills from "./components/skills/Skills";
import Projects from "./components/projects/Projects";
import Logo from "./components/ux/logo/Logo";
import ModeSwitch from "./components/ux/light_dark_mode/ModeSwitch";
import {themes, ThemeContext} from './utils/Theme'
import { useEffect } from "react";
function Loader() {
  const { progress } = useProgress()
  return <Html center>{progress} % loaded</Html>
}


export default function App() {
  const theme = useContext(ThemeContext);

/* -------------------+-------------- */

  var currentTheme= themes.light;
  document.body.style.backgroundColor = currentTheme.primary;
  document.body.style.color = currentTheme.text;
  return (
    
       <ThemeContext.Provider value={currentTheme}>
    {/* <Logo/> */}
    <ModeSwitch/>
    <BottomBar/>
    <Scroll/>
<Welcome/>
<Socials/>
      <Canvas className="canvas"
      > 

            <Suspense fallback={<Loader/>}>
          <EffectComposer multisampling={0} disableNormalPass={true} >
          
      </EffectComposer>
      <Box />
      
      <OrbitControls enabled={false}/>
        </Suspense>
      </Canvas>
      <Section content={<About/>} id={'about'}/>
      <Section content={<Skills/>}/>
      <Section content={<Projects/>} id={'projects'}/>
      </ThemeContext.Provider>
 
  );
 
}

Solution

  • Alright, I found the answer already! Context providers cannot pass down values into elements. I redeclared the <ThemeContext.Provider> inside the canvas tags as well, and it worked!