reactjs nextjs react state not update当函数解析到子组件时

6tqwzwtp  于 2023-05-22  发布在  React
关注(0)|答案(1)|浏览(107)
"use client";

import { EntityType, World } from "@/types/World";
import React, { useState } from "react";
import dynamic from "next/dynamic";
;

let RayTracingPage = dynamic(()=>import("./RayTracingCanvas"));
let initialMovements = [0,0,0,0,0]
export default async function Home() {
    const [world, setWorld] = useState<World>({
    
        lights: [
            {
                x: -30,
                y: -10,
                z: 20,
            },
        ],

        camera: {
            point: {
                x: 0,
                y: 1.8,
                z: 10,
            },
            fov: 45,
            direction: {
                x: 0,
                y: 3,
                z: 0,
            },
        },

        entities: [
            {
                type: EntityType.Sphere,
                point: {
                    x: 0,
                    y: 3.5,
                    z: -3,
                },
                color: { // 0=> purple
                    r: 155,
                    g: 50,
                    b: 155,
                    a: 255
                },
                specular: 0.2,
                lambert: 0.7,
                ambient: 0.1,          p0:0,

                radius: 1,
                speed: 0.1
            },
            {
                type: EntityType.Sphere,
                point: {
                    x: -4,
                    y: 3.5,
                    z: -1,
                },
                color: { // 1 => red
                    r: 155,
                    g: 25,
                    b: 40,
                    a:255
                },
                specular: 0.1,
                lambert: 0.9,
                ambient: 0.0,
                radius: 0.2,          p0:0,

                speed: 0.2
            },
            {
                type: EntityType.Sphere,
                point: { // 2 => green
                    x: -7,
                    y: 3.5,
                    z: -10,
                },
                color: {
                    r: 34,
                    g: 255,
                    b: 34,
                    a: 255
                },
                specular: 0.2,
                lambert: 0.7,
                ambient: 0.1,
                radius: 0.1,          p0:0,

                speed: 0.3
            },
            {
            type: EntityType.Sphere,
            point: {
                x: -8,
                y: 3.5,
                z: -5,
            },
            color: { // 3 => dark blue
                r: 34,
                g: 13,
                b: 134,
                a: 255
            },
            specular: 0.2,
            lambert: 0.7,
            ambient: 0.1,
            radius: 0.3,          p0:0,

            speed: 0.4
            },
            {
            type: EntityType.Sphere,
            point: {
                x: -14,
                y: 3.5,
                z: -3,
            },
            color: { // 4 => yellow
                r: 230,
                g: 230,
                b: 21,
                a: 255
            },
            specular: 0.2,
            lambert: 0.7,
            ambient: 0.1,
            radius: 0.5,
            p0:0,
            speed: 0.5
        },
        ]
    });
    const [movements,setMovements] = useState<number[]>(initialMovements)
    const motionUpdate:()=> World =()=>{
        let newMovements:number[]=[]
        for(let i = 0; i < movements.length; i++){
            newMovements.push(movements[i] + world.entities[i].speed)
        }
        console.log(movements)

        setMovements(newMovements);
        world.entities[0].point.x = Math.sin(movements[0]);
        world.entities[0].point.z = Math.cos(movements[0]);
    
        world.entities[1].point.x = Math.sin(movements[1]) * 2;
        world.entities[1].point.z = -4 + Math.cos(movements[1]) * 2;
    
        world.entities[2].point.x = Math.sin(movements[2]) * 3;
        world.entities[2].point.z = -3 + Math.cos(movements[2]) * 3;
        world.entities[2].point.y = 3.5 + Math.sin(movements[2]) * 3;
    
        world.entities[3].point.x = Math.sin(movements[3]) * 2;
        world.entities[3].point.z = -3 + Math.cos(movements[3]) * 2;
    
        world.entities[4].point.x = Math.sin(movements[4]) * 4;
        world.entities[4].point.z = -3 + Math.cos(movements[4]) * 4;
        world.entities[4].point.y = 3.5 + Math.cos(movements[4]) * 4;
        return world
    }

  return (
    <div>
      <CanvasPage width={1280} height={720} AnimationCallback={motionUpdate}></CanvasPage>
    </div>
  )
}

我的React状态没有每次更新,动作被设置回默认值,任何想法为什么会发生这种情况

const motionUpdate:()=> World =useCallback(()=>{
        setWorld(world=>{
            const newWorld = { ...world };

            setMovements((moves)=>{
                let newMovements:number[]=[]

                for(let i = 0; i < moves.length; i++){
                    newMovements.push(moves[i] + world.entities[i].speed)
                }
                return newMovements
            });
            newWorld.entities[0].point.x = Math.sin(movements[0]);
            newWorld.entities[0].point.z = Math.cos(movements[0]);
        
            newWorld.entities[1].point.x = Math.sin(movements[1]) * 2;
            newWorld.entities[1].point.z = -4 + Math.cos(movements[1]) * 2;
        
            newWorld.entities[2].point.x = Math.sin(movements[2]) * 3;
            newWorld.entities[2].point.z = -3 + Math.cos(movements[2]) * 3;
            newWorld.entities[2].point.y = 3.5 + Math.sin(movements[2]) * 3;
        
            newWorld.entities[3].point.x = Math.sin(movements[3]) * 2;
            newWorld.entities[3].point.z = -3 + Math.cos(movements[3]) * 2;
        
            newWorld.entities[4].point.x = Math.sin(movements[4]) * 4;
            newWorld.entities[4].point.z = -3 + Math.cos(movements[4]) * 4;
            newWorld.entities[4].point.y = 3.5 + Math.cos(movements[4]) * 4;
            return newWorld
        })
        return world
        
    },[movements, world])

尝试用上面的函数更新我的代码,画布仍然没有更新,我假设这是因为太多的调用motionUpdate函数阻止状态更新,也许我需要使用reduce函数,什么是最好的解决方案?

wxclj1h5

wxclj1h51#

请正确格式化您的代码,因为有一个孤独的分号在那里。此外,您直接改变了world状态,而不是调用setWorld
在你的函数中,你可以做如下的事情:

// ...

setWorld((previous) => {
  const newWorld = { ...previous };
  
  newWorld.entities[0].point.x = Math.sin(movements[0]);
  newWorld.entities[0].point.z = Math.cos(movements[0]);
    
  newWorld.entities[1].point.x = Math.sin(movements[1]) * 2;
  newWorld.entities[1].point.z = -4 + Math.cos(movements[1]) * 2;
    
  newWorld.entities[2].point.x = Math.sin(movements[2]) * 3;
  newWorld.entities[2].point.z = -3 + Math.cos(movements[2]) * 3;
  newWorld.entities[2].point.y = 3.5 + Math.sin(movements[2]) * 3;
    
  newWorld.entities[3].point.x = Math.sin(movements[3]) * 2;
  newWorld.entities[3].point.z = -3 + Math.cos(movements[3]) * 2;
    
  newWorld.entities[4].point.x = Math.sin(movements[4]) * 4;
  newWorld.entities[4].point.z = -3 + Math.cos(movements[4]) * 4;
  newWorld.entities[4].point.y = 3.5 + Math.cos(movements[4]) * 4;
  
  return newWorld;
});

还可以考虑将你的函数 Package 在一个useCallback中,否则它将在每次渲染时重新创建。

注意

没有必要一遍又一遍地重复同一句话。

相关问题