gpt4 book ai didi

reactjs - useRef() 的钩子(Hook)调用无效

转载 作者:行者123 更新时间:2023-12-03 07:50:40 27 4
gpt4 key购买 nike

我试图以动态方式分配引用,但在 useRef 时收到错误“无效的钩子(Hook)调用。钩子(Hook)只能在函数组件的主体内部调用”。这里:

const [subsistemaPlanetario, setSubsistemaPlanetario] = useState([]);
const planetRefs = useRef({});

useEffect(() => {
async function fetchSubsistemaPlanetario() {
try {
const fetchedSubsistemaPlanetario = await getSubsistemaPlanetario();
setSubsistemaPlanetario(fetchedSubsistemaPlanetario);

fetchedSubsistemaPlanetario.forEach((planeta) => {
const camelCaseSlug = planeta.padre.slug.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
planetRefs.current[camelCaseSlug] = useRef(); // <------THIS LINE DROP AN ERROR
});
} catch (error) {
console.error(error);
}
}

fetchSubsistemaPlanetario();
}, []);

整个组件:

import {useFrame} from '@react-three/fiber';
import React, {useRef, useEffect, useState} from 'react';
import {Planet} from './Planet.jsx';
import {Satellite} from './Satellite.jsx';
import {Orbiter} from './utils/Orbiter.js';
import {calculateOrbitalPeriod} from './utils/calculateOrbitalPeriod.js';

import {getSubsistemaPlanetario} from './utils/getSubsistemaPlanetario.js';

export const SubsistemaPlanetario = function SubsistemaPlanetario(props) {
let running = true;
let stopRunning = () => (running = false);
let startRunning = () => (running = true);

const [subsistemaPlanetario, setSubsistemaPlanetario] = useState([]);
const planetRefs = useRef({});

useEffect(() => {
// Obtener el subsistema planetario cuando el componente se monta
async function fetchSubsistemaPlanetario() {
try {
const fetchedSubsistemaPlanetario = await getSubsistemaPlanetario();

setSubsistemaPlanetario(fetchedSubsistemaPlanetario);

fetchedSubsistemaPlanetario.forEach((planeta) => {
const camelCaseSlug = planeta.padre.slug.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());

planetRefs.current[camelCaseSlug] = useRef();
console.log(planetRefs);
});
} catch (error) {
console.error(error);
}
}

fetchSubsistemaPlanetario();
}, []);

return (
<>
{subsistemaPlanetario.map((planetaPadre, index) => (
<Planet
key={index}
scale={0.5}
ref={planetRefs.current[index]}
stopRunning={stopRunning}
startRunning={startRunning}
textureType="haumea"
linkTo="areas"
linkToLabel="Areas"
/>
))}
</>
);
};

行星组件

import {forwardRef, useRef, useEffect, useContext, useState} from 'react';
import PropTypes from 'prop-types';
import {useTexture} from '@react-three/drei';
import {useFrame} from '@react-three/fiber';
import barba from '@barba/core';
import {solapaContentAbrir, solapaContentCerrar} from './utils/Solapa.js';
import {planets} from './utils/arrayTexturas.js';

// Define un objeto que mapea los tipos de textura a las rutas de los archivos de textura.
const textureMap = {};

for (const planet of planets) {
textureMap[planet] = `./app/themes/sage/resources/scripts/cosmos/components/textures/${planet}-512.jpg`;
}

export const Planet = forwardRef(function Planet(props, ref) {
// Obtén la ruta de la textura según el tipo especificado en props.textureType.
const texturePath = textureMap[props.textureType] || textureMap.sand;
const texture = useTexture(texturePath);

let rotationX = Math.random();
let rotationY = Math.random();

useFrame((state, delta) => {
ref.current.rotation.x += rotationX * delta;
ref.current.rotation.y += rotationY * delta;
});

return (
<mesh
{...props}
ref={ref}
castShadow
receiveShadow
onPointerEnter={(event) => {
props.stopRunning();
document.body.style.cursor = 'pointer';
solapaContentAbrir('Sección', props.linkToLabel);
event.stopPropagation();
}}
onPointerLeave={(event) => {
props.startRunning();
document.body.style.cursor = 'default';
solapaContentCerrar();
event.stopPropagation();
}}
onClick={(event) => {
barba.go(props.linkTo);
}}
>
<sphereGeometry />
<meshStandardMaterial map={texture} />
</mesh>
);
});

Planet.propTypes = {
stopRunning: PropTypes.func,
startRunning: PropTypes.func,
textureType: PropTypes.oneOf(['haumea', 'mars', 'neptune', 'venus', 'mercury', 'jupiter', 'saturn']),
userData: PropTypes.object,
radius: PropTypes.number,
linkTo: PropTypes.string,
linkToLabel: PropTypes.string,
};

感谢任何帮助。

最佳答案

不确定您到底想在这里实现什么目标。

ref={planetRefs.current[index]}

不会执行任何操作,因为 planetRefs.current 是一个空对象,并且将保持为空对象,因为您没有为其分配任何值它。

planetRefs.current[camelCaseSlug] = useRef();

也不会执行任何操作,因为您不能在不是 react 组件的函数中使用 react hooks


By the way - why you are assigning the ref value as camelCaseSlug but in the render you are trying to access it by index?


可能的解决方案

我认为您应该使用回调引用来代替,以访问渲染的元素:

ref={(ref) => {
planetRefs.current[index] = ref;
}}

注意:请记住使用 forwardRef 包装您的 Planet 组件。

编辑:

您可以完全删除 planetRefs.current[camelCaseSlug] = useRef(); 部分。如果您希望将 planetRefs 中的 refs 保留为 slugs,只需稍微修改回调引用即可:

ref={(ref) => {
const camelCaseSlug = planetaPadre.padre.slug
.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());

planetRefs.current[camelCaseSlug] = ref;
}}

关于reactjs - useRef() 的钩子(Hook)调用无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77203275/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com