繁体   English   中英

useState setter function 没有在反应中更新 state

[英]useState setter function is not updating state in react

我在两个组件CustomCodeEditorEditorFooter中使用useIsDirty挂钩来跟踪编辑器中的代码是否已被修改。 钩子返回一个isDirty state 和一个setIsDirty function 来更新它。 当我在CustomCodeEditor组件中调用setIsDirty(true)时,state 被更新,但是当我在EditorFooter组件中调用setIsDirty(false)时,它似乎没有更新isDirty state。我相信这是因为 EditorFooter 组件确实无法访问更新的 state。任何人,请帮我解决这个问题。

使用是脏的:

import { useEffect, useState } from "react"

const useIsDirty = () => {
  const [isDirty, setIsDirty] = useState(false)

  useEffect(() => {
    const handleBeforeUnload = (event) => {
      if (isDirty) {
        event.preventDefault()
        event.returnValue = ""
        alert("You have unsaved changes, are you sure you want to leave?")
      }
    }
    console.log("Diryt:", isDirty)
    window.addEventListener("beforeunload", handleBeforeUnload)
    return () => {
      window.removeEventListener("beforeunload", handleBeforeUnload)
    }
  }, [isDirty])

  return { isDirty, setIsDirty }
}

export default useIsDirty

自定义代码编辑器

import Editor from "@monaco-editor/react"

import useIsDirty from "../../hooks/useIsDirty"

const CustomCodeEditor = () => {
  const { isDirty, setIsDirty } = useIsDirty()

  console.log("isDirty:", isDirty)
  return (
        <div className="bg-[#1e1e1e] h-full">
          <Editor
            onChange={(value) => {
              updateCode(value || "")
              setIsDirty(true) // updating state
            }}
          />
        </div>
  )
}

export default CustomCodeEditor

编辑器页脚

import Button from "../reusable/Button"

const EditorFooter = () => {
  const { setIsDirty } = useIsDirty()

  const handleSave = async () => {
    setIsDirty(false)
  }

  return (
    <div>
      <Button
        onClick={handleSave}
      >
        Save
      </Button>
      <Button
        onClick={handleSave}
      >
        Submit
      </Button>
    </div>
  )
}

export default EditorFooter

钩子不是 singleton 个实例。当你在某处使用useIsDirty时。它总是创建新实例,与其他实例具有不相关的状态。 如果你想分享这个 state 你需要使用Context

const IsDirtyContext = createContext(undefined);

const IsDirtyProvider = ({ children }): ReactElement => {
     const [isDirty, setIsDirty] = useState(false)
    return <IsDirtyContext.Provider value={{isDirty, setIsDirty}}>{children}</IsDirtyContext.Provider>;
};

然后你应该用IsDirtyProvider把你的组件树包装在你想访问它的地方

之后,您甚至可以创建只返回该上下文的自定义挂钩:

const useIsDirty = () => {
  return useContext(IsDirtyContext)
}

查看您的问题,您似乎正在尝试在两个组件中使用相同的 state。 然而,state 并不是那样工作的。 每当您从不同的组件调用 useIsDirty 时,都会创建一个新实例。

如果要跨两个组件使用 state 值。 您可以使用以下方法之一来执行此操作。

1 - 使用父子层次结构。

脚步

  • 创建一个父组件并将两个组件包装在父组件内。
  • 在父组件中管理 state 并使用 props 传递给子组件。
  • 在子组件中创建一个 function,它将从父组件执行 function。 父组件 function 将保存代码,根据您从子组件收到的任何值更新 state。

现在您应该能够在两个组件之间共享您的 state。


2 - 使用上下文 api。

如果你不了解 api 是什么上下文,下面简单解释一下。

上下文 api 可帮助您在组件之间共享数据,而无需将它们作为 prop 传递给每个组件。

您可以使用上下文 api 中的 createContext 和 useContext 挂钩。

createContext用于创建新的上下文提供程序。

useContext钩子用于全局管理 state。 您可以使用此 function 从上下文中获取值。每当 state 更新时,该值将在全球范围内反映出来。

注意 - 任何需要使用 useContext 中的值的组件都应该包装在 useContext 提供程序组件中。

创建上下文提供程序的步骤。 要创建上下文,您只需要使用 react hook createContext

  • 使用以下代码创建上下文

    const isDirtyContext = createContext();

  • 将您的组件包装在上下文提供程序中

    从 './path/filename' 导入 {IsDirtyContext}

    <IsDirtyContext.Provider value={[isDirty, setIsDirty]}>{children}</IsDirtyContext.Provider>

  • 如果您的上下文在一个单独的文件中,那么您可以使用 import 语句将其导入到任何子组件中。

    从 './path/filename' 导入 {IsDirtyContext}

  • 使用上下文

    const [isDirty] = useContext(IsDirtyContext);

现在 isDirty state 值在所有组件中全局可用。

希望这些信息对您有所帮助。 如果这有助于您理解和解决问题,请点赞。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM