提问人:user573 提问时间:10/16/2023 更新时间:10/16/2023 访问量:42
类组件引用并设置自己的静态变量 - 什么是功能组件的等价物?
Class components referencing and setting their own static variables - what is the functional component equivalent?
问:
使用类组件时,我能够设置静态变量,这些变量将持续存在于类的每个后续实例上。这允许我在组件上设置一种状态,即使多次调用同一组件也是如此。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>
);
};
我相信设置上下文变量可能能够解决这个问题,但我宁愿现在不使用它。我也知道我可以将状态提升到父级,但我想避免这种情况,因为它很可能会导致重新渲染。
这种情况似乎很容易用类组件解决,但这些组件现在已经过时了。有没有一种简单的方法可以纯粹使用功能/组件来做到这一点?
干杯!
答:
任何钩子,无论是 还是 ,都是组件的每个实例。useState
useRef
如果你真的想要一个静态变量1,只需执行与组件完全相同的操作 - 将其存储在对象本身上:class
function
function FunctionComponent({ id }) {
if (FunctionComponent.firstRun) {
console.log('Initial function component render...', id);
FunctionComponent.firstRun = false;
} else {
console.log('Function component has already been rendered before.', id);
}
return (
<div>Hello, function component!</div>
);
}
FunctionComponent.firstRun = true;
不过,更习惯的做法是只在定义函数组件的模块作用域中声明一个变量:
let firstRun = true;
function FunctionComponent({ id }) {
if (firstRun) {
console.log('Initial function component render...', id);
firstRun = false;
} else {
console.log('Function component has already been rendered before.', id);
}
return (
<div>Hello, function component!</div>
);
}
如果不希望日志在每次呈现组件时都出现,而只显示一次,则在装载组件时,可以使用效果或状态的初始值设定项:
let firstRun = true;
function FunctionComponent({ id }) {
useEffect(() => {
if (firstRun) {
console.log('Initial function component mount...', id);
firstRun = false;
} else {
console.log('Function component has already been mounted elsewhere.', id);
}
}, []);
return (
<div>Hello, function component!</div>
);
}
let firstRun = true;
function FunctionComponent({ id }) {
const [isFirst] = useState(() => {
if (firstRun) {
firstRun = false;
return true;
} else {
return false;
}
});
return (
<div>Hello, {isFirst && 'first'} function component!</div>
);
}
1:你可能不想要一个静态变量。对于常量来说,这是可以的,但是一旦你有了有状态的静态变量,它本质上就是全局状态。避免这种情况。
评论
useRef
useState