我有一个计数器和一个console.log()来useEffect记录我状态中的每个变化,但是useEffect在挂载时被调用两次。我正在使用 React 18。这是我项目的CodeSandbox和以下代码:
import { useState, useEffect } from "react";
const Counter = () => {
const [count, setCount] = useState(5);
useEffect(() => {
console.log("rendered", count);
}, [count]);
return (
<div>
<h1> Counter </h1>
<div> {count} </div>
<button onClick={() => setCount(count + 1)}> click to increase </button>
</div>
);
};
export default Counter;
Run Code Online (Sandbox Code Playgroud) 如何能在useEffect钩(或任何其他挂钩的这个问题)可以被用来复制componentWillUnmount?
在传统的类组件中,我将执行以下操作:
class Effect extends React.PureComponent {
componentDidMount() { console.log("MOUNT", this.props); }
componentWillUnmount() { console.log("UNMOUNT", this.props); }
render() { return null; }
}
Run Code Online (Sandbox Code Playgroud)
随着useEffect钩:
function Effect(props) {
React.useEffect(() => {
console.log("MOUNT", props);
return () => console.log("UNMOUNT", props)
}, []);
return null;
}
Run Code Online (Sandbox Code Playgroud)
(完整示例:https : //codesandbox.io/s/2oo7zqzx1n)
这是行不通的,因为返回的“清理”功能会useEffect捕获安装过程中的道具,而不会在卸载过程中捕获道具的状态。
我怎么能获得最新版本的道具的useEffect清理,而不在每一个道具的变化运行的函数体(或清理)?
一个类似的问题没有解决获得最新道具的问题。
该反应文档状态:
如果要运行效果并仅将其清除一次(在挂载和卸载时),则可以传递一个空数组([])作为第二个参数。这告诉React您的效果不依赖于props或state的任何值,因此它不需要重新运行。
但是在这种情况下,我依赖道具...但仅用于清理部分...
今天,另一位开发人员向我提出了一个棘手的问题。她提出以下建议:
A.) 她想在模式关闭时触发一个事件。
B.) 她不希望该事件在任何其他时间触发。
C.) 事件必须与组件的状态保持同步。
一个基本的例子是这样的:
const ModalComponent = () => {
const [ eventData, setEventData ] = useState({ /* default data */ });
useEffect(() => {
return () => {
// happens anytime dependency array changes
eventFire(eventdata);
};
}, [eventData]);
return (
<>
// component details omitted, setEventData used in here
</>
);
};
Run Code Online (Sandbox Code Playgroud)
目的是当模式关闭时,事件触发。但是,用户与模态的交互会导致状态更新,从而更改 的值eventData。这就引出了问题的核心:
eventData数组useEffect会导致它仅在模式关闭时触发,但该值已过时。这是安装组件时的值。eventData在useEffect依赖项数组中都会导致事件反复触发useEffect。解决这个问题的办法是什么?如何访问最新数据但仅在卸载时对其进行操作?
我已经构建了几个模态作为 React 功能组件。它们通过isModalOpen模态关联上下文中的布尔属性显示/隐藏。这非常有效。
Now, for various reasons, a colleague needs me to refactor this code and instead control the visibility of the modal at one level higher. Here's some sample code:
import React, { useState } from 'react';
import Button from 'react-bootstrap/Button';
import { UsersProvider } from '../../../contexts/UsersContext';
import AddUsers from './AddUsers';
const AddUsersLauncher = () => {
const [showModal, setShowModal] = useState(false);
return (
<div>
<UsersProvider>
<Button onClick={() => setShowModal(true)}>Add Users</Button>
{showModal && <AddUsers />}
</UsersProvider>
</div> …Run Code Online (Sandbox Code Playgroud)