当使用类组件时,我能够设置静态变量,这些变量将在类的每个进一步示例上持久化。这允许我在组件上设置一种firstRun
状态,即使多次调用同一个组件也是如此。
我尝试在一个函数式组件中创建这种行为,但是当组件被多次使用时,它似乎每次都忘记了它的状态、引用等。
在下面的代码中,我有两个组件,一个函数和一个类。每个组件在App
中被调用三次。在类组件中,我可以直接设置ClassComponent.firstRun
,然后我可以在同一组件的进一步包含中引用它。在功能组件中,我已经尝试了相同的useRef
,但这似乎只对组件的每个示例有效,并且在每个新组件上都被遗忘。
const { useEffect, useRef } = React;
const FunctionalComponent = (props) => {
const { id } = props;
const mounted = useRef(false);
useEffect(() => {
if (!mounted.current) {
console.log('Initial functional component load...', id);
mounted.current = true;
} else {
console.log('Functional component has already been initialised.', id)
}
}, []);
return (
<div>Hello, functional component!</div>
);
};
class ClassComponent extends React.Component {
constructor(props) {
super(props);
this.createSomething();
}
static firstRun = true;
createSomething() {
if (ClassComponent.firstRun) {
console.log('Initial class component load...', this.props.id);
ClassComponent.firstRun = false;
} else {
console.log('Class component has already been initialised.', this.props.id);
}
}
render() {
return (
<div>Hello, class component!</div>
);
}
}
function App() {
return (
<div>
<ClassComponent id="class-component-1" />
<ClassComponent id="class-component-2" />
<ClassComponent id="class-component-3" />
<FunctionalComponent id="functional-component-1" />
<FunctionalComponent id="functional-component-2" />
<FunctionalComponent id="functional-component-3" />
</div>
)
}
ReactDOM.render(<App />, document.querySelector("#app"));
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
类组件工作良好-我得到一个日志的初始负载,然后两个日志说,它已经初始化-伟大的!然而,功能组件记录三个初始加载消息。
我试过使用useState
,但据我所知,这只适用于重新渲染,而不是单独的组件占用。在使用useRef
时,这似乎也是相同的情况。
我读过关于函数闭包的文章,并试图用下面的代码粗略地实现一个函数,但这又给了我三个Initialised...
日志:
const checkInitial = () => {
let initial = true;
return {
get: function() { return initial },
set: function(state) { initial = state; }
};
}
...
const FunctionalComponent = (props) => {
const { id } = props;
const mounted = useRef(false);
useEffect(() => {
const firstRun = checkInitial();
if (firstRun.get()) {
console.log('Initial...', id);
firstRun.set(true);
} else {
console.log('Already run...', id);
}
}, []);
return (
<div>Hello, functional component!</div>
);
};
我相信设置一个上下文变量可以解决这个问题,但我现在不想使用它。我也知道我可以将状态提升到父级,但我想避免这样做,因为它很可能会导致重新渲染。
这种情况似乎很容易用类组件解决,但这些组件现在已经过时了。有没有一种简单的方法可以完全使用功能性功能/组件来做到这一点?
干杯!干杯!
1条答案
按热度按时间envsm3lx1#
任何钩子,无论是
useState
还是useRef
,都是组件的每个示例。如果你真的想要一个静态变量1,就像你对
class
组件做的那样-把它存储在function
对象本身:更习惯的做法是在定义函数组件的模块作用域中声明一个变量:
如果你不想在每次组件渲染时都显示日志,而只在组件挂载时显示一次,你可以使用一个效果或状态的初始化器:
1:你可能不需要静态变量。这对于常量来说是可以的,但是一旦你有了有状态的静态变量,它本质上就是全局状态。避免这样。