Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.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 事件处理程序get';在设置处理程序之前调用_Javascript_Reactjs_State - Fatal编程技术网

Javascript 事件处理程序get';在设置处理程序之前调用

Javascript 事件处理程序get';在设置处理程序之前调用,javascript,reactjs,state,Javascript,Reactjs,State,我的react应用程序中有这个可重用组件 export const OutsideWrapper = ({ children, onOutside, className }) => { const wrapperRef = useRef(null); const [style, setStyles] = useState({ opacity: 1 }); useEffect(() => { console.log("1. component was m

我的react应用程序中有这个可重用组件

export const OutsideWrapper = ({ children, onOutside, className }) => {
  const wrapperRef = useRef(null);
  const [style, setStyles] = useState({
    opacity: 1
  });
  useEffect(() => {
    console.log("1. component was mounted");
    const i = e => {
      if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
        console.log("3. outside click was trigerred");
        e.preventDefault();
        setStyles({ opacity: 0 });
        setTimeout(() => {
          onOutside();
        }, 100);
      }
    };
    window.addEventListener("click", i, true);
    console.log('2. listener was added');
    return () => {
      console.log("4. listerner was removed");
      window.removeEventListener("click", i, true);
    };
  }, [onOutside]);
  return (
    <div
      ref={wrapperRef}
      style={style}
      className={`outside-wrapper ${className}`}
    >
      {children}
    </div>
  );
};

当React渲染组件时,会调用
窗口.addEventListener
调用
useEffect
,这发生在焦点上。引起焦点的事件不是点击,而是一个
mousedown
。当下一个
mouseup
发生时,也会生成一个被捕获的点击事件。请注意,如果您在输入中按tab键以聚焦,则不会导致错误

有几种方法可以解决这个问题,但我的建议是忽略在输入本身上发生的单击事件

这里有一个例子:我向
添加了一个ref,将其传递到
外部包装器中,并为新的ref添加了一个类似于您为
包装器ref
所做的检查

function Test() {
  const [down, setDown] = React.useState(false);
  const focusRef = React.useRef();
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>
        <input ref={focusRef} onFocus={() => setDown(true)} />
        {down && (
          <OutsideWrapper
            onOutside={() => setDown(false)}
            focusedRef={focusRef}
            className="input-wrapper"
          >
            children
          </OutsideWrapper>
        )}
      </h2>
    </div>
  );
}

const OutsideWrapper = ({ children, onOutside, className, focusedRef }) => {
  const wrapperRef = React.useRef(null);
  const [style, setStyles] = React.useState({
    opacity: 1
  });
  React.useEffect(() => {
    console.log("1. component was mounted");
    const i = e => {
      console.log(e.target, wrapperRef.current);
      if (
        wrapperRef.current &&
        !wrapperRef.current.contains(e.target) &&
        focusedRef.current !== e.target
      ) {
        console.log("3. outside click was trigerred");
        e.preventDefault();
        setStyles({ opacity: 0 });
        setTimeout(() => {
          onOutside();
        }, 100);
      }
    };
    window.addEventListener("click", i, true);
    console.log("2. listener was added");
    return () => {
      console.log("4. listerner was removed");
      window.removeEventListener("click", i, true);
    };
  }, [onOutside, focusedRef]);
  return (
    <div
      ref={wrapperRef}
      style={style}
      className={`outside-wrapper ${className}`}
    >
      {children}
    </div>
  );
};
功能测试(){
const[down,setDown]=React.useState(false);
const focusRef=React.useRef();
返回(
你好,代码沙盒
设置(正确)}/>
{向下&&(
设置(错误)}
focusedRef={focusRef}
className=“输入包装器”
>
儿童
)}
);
}
const OutsideWrapper=({子项,外部,类名,focusedRef})=>{
const wrapperRef=React.useRef(null);
const[style,setStyles]=React.useState({
不透明度:1
});
React.useffect(()=>{
控制台日志(“1.组件已安装”);
常数i=e=>{
日志(如target、wrapperRef.current);
如果(
包装器参考电流&&
!wrapperRef.current.contains(例如目标)&&
focusedRef.current!==e.target
) {
console.log(“3.触发外部点击”);
e、 预防默认值();
setStyles({opacity:0});
设置超时(()=>{
onOutside();
}, 100);
}
};
window.addEventListener(“单击”,i,true);
console.log(“添加了2.listener”);
return()=>{
console.log(“4.listerner被删除”);
window.removeEventListener(“单击”,i,true);
};
},[onOutside,focusedRef]);
返回(
{儿童}
);
};
function Test() {
  const [down, setDown] = React.useState(false);
  const focusRef = React.useRef();
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>
        <input ref={focusRef} onFocus={() => setDown(true)} />
        {down && (
          <OutsideWrapper
            onOutside={() => setDown(false)}
            focusedRef={focusRef}
            className="input-wrapper"
          >
            children
          </OutsideWrapper>
        )}
      </h2>
    </div>
  );
}

const OutsideWrapper = ({ children, onOutside, className, focusedRef }) => {
  const wrapperRef = React.useRef(null);
  const [style, setStyles] = React.useState({
    opacity: 1
  });
  React.useEffect(() => {
    console.log("1. component was mounted");
    const i = e => {
      console.log(e.target, wrapperRef.current);
      if (
        wrapperRef.current &&
        !wrapperRef.current.contains(e.target) &&
        focusedRef.current !== e.target
      ) {
        console.log("3. outside click was trigerred");
        e.preventDefault();
        setStyles({ opacity: 0 });
        setTimeout(() => {
          onOutside();
        }, 100);
      }
    };
    window.addEventListener("click", i, true);
    console.log("2. listener was added");
    return () => {
      console.log("4. listerner was removed");
      window.removeEventListener("click", i, true);
    };
  }, [onOutside, focusedRef]);
  return (
    <div
      ref={wrapperRef}
      style={style}
      className={`outside-wrapper ${className}`}
    >
      {children}
    </div>
  );
};