在React js中只加载一次组件



所以我有一个React应用程序它有2页假设第一个是Home,第二个是My Portfolio Section我的投资组合部分有两个功能组件

Home.js

import React from 'react'
const Home = () => {
return (
<h1>Home Screen</h1>
)
}
export default Home

投资组合部分

import React from 'react'
import Projects from '../components/Projects'
import Testimonials from '../components/Testimonials'
const Portfolio = () => {
return (
<>
<h1>Portfolio</h1>
<Projects/>
<Testimonials/>
</>
)
}
export default Portfolio 

当我访问Home,Portfolio时,一切都加载良好,但当我再次访问它们时,它们每次都会重新加载

我不希望Portfolio部分中的Projects组件加载多次我希望它只在启动/启动网站时加载一次,甚至在访问Portfolio部分(即后台(之前,因为它有很大的文件需要时间加载,并且在用户自愿刷新页面之前保持不变。

该组件中有一些使用three.js的三维模型所以它不是一个静态站点它将有自己的动画但是每次访问页面时加载整个组件将花费大量时间

但是证明组件将动态更改

因此,在其中两个组件中,我希望其中一个组件保持不变而不重新加载和其他动态改变

如何使组件只加载一次任何建议都会对我有所帮助我看了UseMemo,但我不知道这是否对我有帮助如果是的话,有人能解释一下如何在我的情况下使用吗

首次渲染相关组件(Projects(时,创建动画,并将其缓存在组件外部的变量中(示例中为let animation(。每当组件被挂载时,从外部变量获取动画并启动它。当它被卸载时,停止动画。

注意:如果只渲染组件的单个实例,则此操作会起作用。如果要渲染多个实例,则需要为每个实例创建一个系统来缓存并重新渲染动画——可能是某种为每个实例具有恒定id的Map。

示例-切换页面,动画将继续

const { Fragment, useState, useEffect, useRef } = React
let animation
const Projects = () => {
const container = useRef();

useEffect(() => {    
if(!animation) {
animation = createAnimation()
}

container.current.appendChild(animation.domElement)

animation.start()

return () => animation.stop()
}, [])
return (
<div ref={container} /> 
)
}
const Home = () => (
<span>Home Screen</span>
)
const Portfolio = () => (
<Fragment>
<span>Portfolio</span>
<Projects />
</Fragment>
)
const App = () => {
const [showPortfolio, setShowPortfolio] = useState(false)
return (
<div>
<button 
onClick={() => setShowPortfolio(!showPortfolio)}>
Toggle
</button>

{showPortfolio ? <Portfolio /> : <Home />}
</div>
)
}
ReactDOM.render(
<App />,
root
)
function createAnimation() {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(20, window.innerWidth / window.innerHeight, 1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth / 2, window.innerHeight / 2);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({
color: 0x00ff00
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
let requestId;
const animate = () => {
requestId = requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
};
return {
start: animate,
stop: () => cancelAnimationFrame(requestId),
domElement: renderer.domElement
}
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r126/three.min.js" integrity="sha512-n8IpKWzDnBOcBhRlHirMZOUvEq2bLRMuJGjuVqbzUJwtTsgwOgK5aS0c1JA647XWYfqvXve8k3PtZdzpipFjgg==" crossorigin="anonymous"></script>
<div id="root"></div>

最新更新