Javascript 事件侦听器之间未按预期更新状态

Javascript 事件侦听器之间未按预期更新状态,javascript,reactjs,lodash,react-hooks,Javascript,Reactjs,Lodash,React Hooks,我有两个输入 电子邮件地址 名字 初始加载时,将隐藏第一个名称 单击电子邮件地址输入,将隐藏一个div并显示名字输入。 它还将在输入上方隐藏一个div,输入将填充该空间 现在,我正在寻找的功能是在用户单击电子邮件地址输入后,然后用户单击名字。名字不应消失,div返回 为此,目前,我在onBlur事件侦听器上添加了一个lodash去抖动延迟,以等待用户是否关注名字输入 我有一个状态变量onBlurWait,它默认为false,当用户关注名字输入时,它会更新为true 关注名字输入,调用onBlur

我有两个输入

电子邮件地址

名字

初始加载时,将隐藏第一个名称

单击电子邮件地址输入,将隐藏一个div并显示名字输入。 它还将在输入上方隐藏一个div,输入将填充该空间

现在,我正在寻找的功能是在用户单击电子邮件地址输入后,然后用户单击名字。名字不应消失,div返回

为此,目前,我在
onBlur
事件侦听器上添加了一个lodash去抖动延迟,以等待用户是否关注名字输入

我有一个状态变量
onBlurWait
,它默认为
false
,当用户关注名字输入时,它会更新为
true

关注名字输入,调用
onBlur
事件侦听器检查
onBlurWait
状态的值。现在,此侦听器只返回一个
console.log
onBlurWait

电子邮件地址输入中的
onBlur
似乎在名字输入的
onFocus
之前被调用。因此,
onBlurWait
状态似乎没有得到更新,因此
onBlur
事件侦听器中的
console.log
将返回false

这是一个可以帮助你玩的游戏,所以你可以很有希望地理解我上面提到的内容

下面是我的组件

import React, { useState } from "react";
import ReactDOM from "react-dom";
import _ from "lodash";

import InputControl from "./InputControl";

import "./styles.css";

const App = () => {
  const [hideContent, setHideContent] = useState(false);
  const [emailSignUpRef, setEmailSignUpRef] = useState(null);
  const [firstNameSignUpRef, setFirstNameEmailSignUpRef] = useState(null);
  const [onBlurWait, setOnBlurWait] = useState(false);

  let registerEmailInput = null;
  let firstNameInput = null;

  // If you click on email address then on first name, I would expect the console.log below to return true
  // due to when a user focuses on the first name input the handleInputFocus function gets called
  // inside that function, setOnBlurWait(true); is ran updating the value of onBlurWait to true
  // But it seems like it has not actually been updated
  // Now when you click on email address to first name, back to email address and first name again, the console log now returns true?
  const waitOnUpdateState = _.debounce(() => console.log(onBlurWait), 2000);
  const hideContentAfterState = _.debounce(
    () =>
      setHideContent(
        emailSignUpRef.length > 0 || firstNameSignUpRef.length > 0 || onBlurWait
      ),
    2000
  );

  const handleOnFocus = event => {
    setEmailSignUpRef(registerEmailInput.value);
    setFirstNameEmailSignUpRef(firstNameInput.value);
    setHideContent(true);
  };

  const handleOnInput = () => {
    setEmailSignUpRef(registerEmailInput.value);
    setFirstNameEmailSignUpRef(firstNameInput.value);
  };

  const handleInputFocus = () => {
    console.log("clicked on first name, onBlurWait should be set as true");
    setOnBlurWait(true);
  };

  const handleOnBlur = () => {
    console.log("clicked away from email address");
    // waitOnUpdateState is just a test function to return a console log, hideContentAfterState is what is going to be used
    waitOnUpdateState();
    hideContentAfterState();
  };

  return (
    <div className="App">
      <div className={hideContent ? "hidden" : "visible"} />
      <InputControl
        autoComplete="off"
        refProp={input => {
          registerEmailInput = input;
        }}
        onInput={handleOnInput}
        onFocus={handleOnFocus}
        onBlur={handleOnBlur}
        type="text"
        name="emailAddressRegister"
        placeholder="Email address"
        label="Email Address"
      />
      <InputControl
        className={
          !hideContent ? "InputControl--hidden" : "InputControl--visible"
        }
        autoComplete="off"
        refProp={input => {
          firstNameInput = input;
        }}
        onInput={handleOnInput}
        onFocus={handleInputFocus}
        type="text"
        name="firstName"
        placeholder="First Name"
        label="First Name"
      />
      <input type="submit" value="Submit" />
    </div>
  );
};

export default App;
import React,{useState}来自“React”;
从“react dom”导入react dom;
从“洛达斯”进口;
从“/InputControl”导入InputControl;
导入“/styles.css”;
常量应用=()=>{
const[hideContent,setHideContent]=useState(false);
const[emailSignUpRef,setEmailSignUpRef]=useState(null);
const[firstNameSignUpRef,setFirstNameEmailSignUpRef]=useState(null);
常量[onBlurWait,setOnBlurWait]=useState(false);
让registerEmailInput=null;
让firstNameInput=null;
//如果您单击电子邮件地址,然后单击名字,我希望下面的console.log返回true
//由于用户将注意力集中在名字输入上,因此会调用handleInputFocus函数
//在该函数中,运行setOnBlurWait(true);将onBlurWait的值更新为true
//但看起来它实际上并没有被更新
//现在,当您再次单击电子邮件地址至第一个名称、返回电子邮件地址和第一个名称时,控制台日志现在返回true?
const waitOnUpdateState=u.debounce(()=>console.log(onBlurWait),2000年);
常量hideContentAfterState=u0.debounce(
() =>
setHideContent(
emailSignUpRef.length>0 | | firstNameSignUpRef.length>0 | | onBlurWait
),
2000
);
const handleOnFocus=事件=>{
setEmailSignUpRef(registerEmailInput.value);
setFirstNameEmailSignUpRef(firstNameInput.value);
setHideContent(真);
};
常量输入=()=>{
setEmailSignUpRef(registerEmailInput.value);
setFirstNameEmailSignUpRef(firstNameInput.value);
};
常量handleInputFocus=()=>{
log(“单击名字,onBlurWait应设置为true”);
设置模糊等待(true);
};
常量handleOnBlur=()=>{
console.log(“点击远离电子邮件地址”);
//waitOnUpdateState只是一个返回控制台日志的测试函数,hideContentAfterState就是要使用的
waitOnUpdateState();
HideContentState();
};
返回(
{
registerEmailInput=输入;
}}
onInput={handleOnInput}
onFocus={handleOnFocus}
onBlur={handleOnBlur}
type=“text”
name=“emailAddressRegister”
占位符=“电子邮件地址”
label=“电子邮件地址”
/>
{
firstNameInput=输入;
}}
onInput={handleOnInput}
onFocus={handleInputFocus}
type=“text”
name=“firstName”
占位符=“名字”
label=“名字”
/>
);
};
导出默认应用程序;

考虑简化,你想得太多了

onFocus
onBlur
都将
relatedTarget
作为其属性之一接收。在
onBlur
的情况下,
relatedTarget
target
的DOM元素


您可以处理
blur
事件,并将事件的
relatedTarget
属性与输入引用进行比较。然后,您将能够确定焦点是转移到页面上的其他表单元素还是其他DOM元素。

感谢您的回答,当将
事件作为参数传递给blur时,
事件。relatedTarget
将以
null
的形式返回?我已经更新了CodeSandbox,因此您可以看到实际上,刚刚意识到它是
null
,因为我单击的是主体而不是元素。再次感谢!有用信息:)