Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/431.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用React钩子卸载组件时如何访问状态?_Javascript_Reactjs_State_React Hooks_Use Effect - Fatal编程技术网

Javascript 使用React钩子卸载组件时如何访问状态?

Javascript 使用React钩子卸载组件时如何访问状态?,javascript,reactjs,state,react-hooks,use-effect,Javascript,Reactjs,State,React Hooks,Use Effect,使用常规React,可能会出现以下情况: class NoteEditor extends React.PureComponent { constructor() { super(); this.state = { noteId: 123, }; } componentWillUnmount() { logger('This note has been closed: ' + t

使用常规React,可能会出现以下情况:

class NoteEditor extends React.PureComponent {

    constructor() {
        super();

        this.state = {
            noteId: 123,
        };
    }

    componentWillUnmount() {
        logger('This note has been closed: ' + this.state.noteId);
    }

    // ... more code to load and save note

}
在React钩子中,可以这样写:

function NoteEditor {
    const [noteId, setNoteId] = useState(123);

    useEffect(() => {
        return () => {
            logger('This note has been closed: ' + noteId); // bug!!
        }
    }, [])

    return '...';
}
useffect
返回的内容将在卸载组件之前只执行一次,但是状态(如上面的代码所示)将是过时的

一个解决方案是将
noteId
作为依赖项传递,但是效果将在每个渲染上运行,而不是只运行一次。或者使用引用,但这很难维护

那么,是否有任何推荐的模式可以使用React钩子实现这个功能呢

使用常规React,可以从组件中的任何位置访问状态,但是使用hook,似乎只有复杂的方式,每种方式都有严重的缺点,或者我只是缺少了一些东西

有什么建议吗?

useState()
useReducer()
的一种特殊形式,因此您可以替换一个完整的减速机以获得当前状态并绕过关闭问题

记事本编辑器

import React,{useffect,useReducer}来自“React”;
功能减速机(状态、动作){
开关(动作类型){
案例“集合”:
返回动作。有效载荷;
案例“卸载”:
console.log(“此便笺已关闭:+状态);//此便笺已关闭:201
打破
违约:
抛出新错误();
}
}
函数注释编辑器({initialNoteId}){
const[noteId,dispatch]=useReducer(reducer,initialNoteId);
useEffect(函数logBeforeUnMount()){
return()=>dispatch({type:“unMount”});
}, []);
useEffect(函数changeIdSideEffect(){
设置超时(()=>{
分派({type:“set”,有效负载:noteId+1});
}, 1000);
}, []);
返回{noteId};
}
导出默认记事本编辑器;
应用程序

import React,{useState,useffect}来自“React”;
导入“/styles.css”;
从“/note editor”导入NoteEditor;
导出默认函数App(){
const[notes,setNotes]=useState([100200300]);
useffect(函数removeNote(){
设置超时(()=>{
setNotes([100300]);
}, 2000);
}, []);
返回(
你好,代码沙盒
开始编辑,看看神奇的发生!
{notes.map(note=>(
))}
);
}
useRef()拯救

由于ref是可变的,并且在组件的生命周期内存在,因此每当更新时,我们可以使用它来存储当前值,并且仍然可以通过ref的value.current属性在useffect的清理功能中访问该值

因此,将有一个额外的useffect(),以在状态更改时保持ref的值更新

示例代码段

const [value, setValue] = useState();
const valueRef = useRef();

useEffect(() => {
  valueRef.current = value;
}, [value]);

useEffect(() => {
  return function cleanup() {
    console.log(valueRef.current);
  };
}, []);

感谢这本书的作者。深度潜水请参考此链接。

“错综复杂的方式”:挂钩往往比基于类的挂钩简单得多。“严重缺陷”:我很想知道这些缺陷是什么。“但这很难维持”:为什么裁判很难维持?当
nodeId
更改时更新ref,并使用当前的
useffect
读取它?这是否回答了您的问题?“当nodeId更改时更新ref”-这意味着每次nodeId更改时都有两个变量而不是一个变量要更新。当然可以做到,但这并不简单。事实上,即使React-Hooks文档也建议不要使用ref(尽管它们没有说明应该使用什么)。这可能是其中之一。或者,依赖正在卸载的组件来跟踪某个对象是否已关闭可能不是最好的方法,“但效果将在每个渲染上运行”-应改为“但效果将在更改noteId时运行”。从技术上讲,这不允许您访问“使用效果清理”功能中的状态。
useRef()
hook的当前属性应该引用state,然后您可以在cleanup中直接访问state。当然可以使用Refs,但是您现在需要保持同步的两个值,而不是一个值。