使用 React Hooks 卸载组件时如何访问状态? [英] How to access state when component unmount with React Hooks?

查看:99
本文介绍了使用 React Hooks 卸载组件时如何访问状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用常规 React 可能会有这样的事情:

class NoteEditor 扩展 React.PureComponent {构造函数(){极好的();this.state = {noteId: 123,};}componentWillUnmount() {logger('此笔记已关闭:' + this.state.noteId);}//... 加载和保存笔记的更多代码}

在 React Hooks 中,可以这样写:

function NoteEditor {const [noteId, setNoteId] = useState(123);useEffect(() => {返回 () =>{logger('此笔记已关闭:' + noteId);//漏洞!!}}, [])返回 '​​...';}

useEffect 返回的内容只会在组件卸载前执行一次,但是状态(如上面的代码中所示)将是陈旧的.

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

那么有没有推荐的模式来使用 React Hook 实现这一点?

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

有什么建议吗?

解决方案

useState()useReducer() 的一种特殊形式,因此你可以替代完整的 reducer获取当前状态并解决关闭问题.

笔记编辑器

import React, { useEffect, useReducer } from "react";功能减速器(状态,动作){开关(动作.类型){案例设置":返回 action.payload;案例卸载":console.log("此笔记已关闭:" + state);//此笔记已关闭:201休息;默认:抛出新的错误();}}function NoteEditor({ initialNoteId }) {const [noteId, dispatch] = useReducer(reducer, initialNoteId);useEffect(function logBeforeUnMount() {返回 () =>dispatch({ type: "unMount" });}, []);useEffect(function changeIdSideEffect() {setTimeout(() => {dispatch({ type: "set", payload: noteId + 1 });}, 1000);}, []);返回<div>{noteId}</div>;}导出默认 NoteEditor;

应用

import React, { useState, useEffect } from "react";导入./styles.css";从./note-editor"导入 NoteEditor;导出默认函数 App() {const [notes, setNotes] = useState([100, 200, 300]);useEffect(function removeNote() {setTimeout(() => {setNotes([100, 300]);}, 2000);}, []);返回 (<div className="应用程序"><h1>Hello CodeSandbox</h1><h2>开始编辑,看看神奇的事情发生了!</h2>{notes.map(note => (<NoteEditor key={`Note${note}`} initialNoteId={note}/>))}

);}

With regular React it's possible to have something like this:

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

}

In React Hooks, one could write this:

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

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

    return '...';
}

What's returned from useEffect will be executed only once before the component unmount, however the state (as in the code above) would be stale.

A solution would be to pass noteId as a dependency, but then the effect would run on every render, not just once. Or to use a reference, but this is very hard to maintain.

So is there any recommended pattern to implement this using React Hook?

With regular React, it's possible to access the state from anywhere in the component, but with hooks it seems there are only convoluted ways, each with serious drawbacks, or maybe I'm just missing something.

Any suggestion?

解决方案

useState() is a specialized form of useReducer(), so you can substitute a full reducer to get the current state and get around the closure problem.

NoteEditor

import React, { useEffect, useReducer } from "react";

function reducer(state, action) {
  switch (action.type) {
    case "set":
      return action.payload;
    case "unMount":
      console.log("This note has been closed: " + state); // This note has been closed: 201
      break;
    default:
      throw new Error();
  }
}

function NoteEditor({ initialNoteId }) {
  const [noteId, dispatch] = useReducer(reducer, initialNoteId);

  useEffect(function logBeforeUnMount() {
    return () => dispatch({ type: "unMount" });
  }, []);

  useEffect(function changeIdSideEffect() {
    setTimeout(() => {
      dispatch({ type: "set", payload: noteId + 1 });
    }, 1000);
  }, []);

  return <div>{noteId}</div>;
}
export default NoteEditor;

App

import React, { useState, useEffect } from "react";
import "./styles.css";
import NoteEditor from "./note-editor";

export default function App() {
  const [notes, setNotes] = useState([100, 200, 300]);

  useEffect(function removeNote() {
    setTimeout(() => {
      setNotes([100, 300]);
    }, 2000);
  }, []);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      {notes.map(note => (
        <NoteEditor key={`Note${note}`} initialNoteId={note} />
      ))}
    </div>
  );
}

这篇关于使用 React Hooks 卸载组件时如何访问状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆