react function running twice thrice | ts

huangapple go评论79阅读模式
英文:

react function running twice thrice | ts

问题

这里大家好。我有一个下拉组件,在其中我传递了选项,当点击这些选项时,我使用R3F导入3D模型。它工作得很好,但唯一的问题是当页面第一次加载时,前2次或4次点击会导入完全随机的模型,这不是我打算导入的模型,但它正在发生。请看一下下面的代码,看看有什么问题。

import {
useState,
useEffect,
useRef,
Dispatch,
SetStateAction,
} from "react";
const useOnClickOutside = (
ref: React.RefObject,
handler: () => void
) => {
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
handler();
}
};

document.addEventListener("mousedown", handleClickOutside);

return () => {
  document.removeEventListener("mousedown", handleClickOutside);
};

}, [ref, handler]);
};

interface Option {
name: string;
value: string | number;
image: string;
id: string;
}

interface DropdownProps {
options: Option[];
title: string;
xAxis: number;
yAxis: number;
zAxis: number;
SysmexArray: number[][];
setSysmexArray: Dispatch<SetStateAction<number[][]>>;
cr10_no_7thArray: number[][];
setCr10_no_7thArray: Dispatch<SetStateAction<number[][]>>;
ID: string;
setID: Dispatch<SetStateAction>;
}

const Dropdown: React.FC = (props) => {
const [isOpen, setIsOpen] = useState(false);
const [selectedOption, setSelectedOption] = useState<Option | undefined>(
undefined
);
const dropdownRef = useRef(null);

const toggleDropdown = () => setIsOpen(!isOpen);

useOnClickOutside(dropdownRef, () => setIsOpen(false));

useEffect(() => {
const handleEscapeKeyPress = (event: KeyboardEvent) => {
if (event.key === "Escape") {
setIsOpen(false);
}
};

document.addEventListener("keydown", handleEscapeKeyPress);

return () => {
  document.removeEventListener("keydown", handleEscapeKeyPress);
};

}, []);

/**/
/这个函数没有正常工作 /
/
*/
const handleOptionClick = (option: Option) => {
setSelectedOption(option);
setIsOpen(false);
if (selectedOption?.name === "m-st") {
props.setID(() =>{

    props.setSysmexArray(() => [
      ...props.SysmexArray,
      [props.xAxis, props.yAxis, props.zAxis],
    ]);
  
    return "m-st"});
  }
if (selectedOption?.name === "CR10") {
  props.setID(() => {
    
    props.setCr10_no_7thArray(() => [
      ...props.cr10_no_7thArray,
      [props.xAxis, props.yAxis, props.zAxis],
    ]);
   
    return "r-cr10"});
}

};

return (


{isOpen && (

    {props.options.map((option) => (
    <li
    key={option.value}
    className="flex flex-col justify-center items-center px-4 py-2 text-sm text-gray-700 cursor-pointer hover:bg-gray-100"
    onClick={() => handleOptionClick(option)}
    >
    {option.name}{" "}

                <div className="text-center">{option.name}</div>
              </li>
            ))}
          </ul>
        </div>
      )}
    </div>
    

    );
    };

    export default Dropdown;

    英文:

    Here there everyone. I've a dropdown component in which I'm passing options and on clicking of those options I'm importing 3d models with R3F. so its working fine but the only catch is when the page loads for the first time first 2 or 4 clicks import totally random models ones that I dont indent to import but its happening. below is the code please take a look what's wrong with it.

    import {
      useState,
      useEffect,
      useRef,
      Dispatch,
      SetStateAction,
    } from &quot;react&quot;;
    const useOnClickOutside = &lt;T extends HTMLElement&gt;(
      ref: React.RefObject&lt;T&gt;,
      handler: () =&gt; void
    ) =&gt; {
      useEffect(() =&gt; {
        const handleClickOutside = (event: MouseEvent) =&gt; {
          if (ref.current &amp;&amp; !ref.current.contains(event.target as Node)) {
            handler();
          }
        };
    
        document.addEventListener(&quot;mousedown&quot;, handleClickOutside);
    
        return () =&gt; {
          document.removeEventListener(&quot;mousedown&quot;, handleClickOutside);
        };
      }, [ref, handler]);
    };
    
    interface Option {
      name: string;
      value: string | number;
      image: string;
      id: string;
    }
    
    interface DropdownProps {
      options: Option[];
      title: string;
      xAxis: number;
      yAxis: number;
      zAxis: number;
      SysmexArray: number[][];
      setSysmexArray: Dispatch&lt;SetStateAction&lt;number[][]&gt;&gt;;
      cr10_no_7thArray: number[][];
      setCr10_no_7thArray: Dispatch&lt;SetStateAction&lt;number[][]&gt;&gt;;
      ID: string;
      setID: Dispatch&lt;SetStateAction&lt;string&gt;&gt;;
    }
    
    const Dropdown: React.FC&lt;DropdownProps&gt; = (props) =&gt; {
      const [isOpen, setIsOpen] = useState(false);
      const [selectedOption, setSelectedOption] = useState&lt;Option | undefined&gt;(
        undefined
      );
      const dropdownRef = useRef&lt;HTMLDivElement&gt;(null);
    
      const toggleDropdown = () =&gt; setIsOpen(!isOpen);
    
      useOnClickOutside(dropdownRef, () =&gt; setIsOpen(false));
    
      useEffect(() =&gt; {
        const handleEscapeKeyPress = (event: KeyboardEvent) =&gt; {
          if (event.key === &quot;Escape&quot;) {
            setIsOpen(false);
          }
        };
        
        document.addEventListener(&quot;keydown&quot;, handleEscapeKeyPress);
    
        return () =&gt; {
          document.removeEventListener(&quot;keydown&quot;, handleEscapeKeyPress);
        };
      }, []);
    
    
      /****************************************/
    /*THIS FUNCTION IS NOT WORKING PROPERLY */
    /**************************************** */
      const handleOptionClick = (option: Option) =&gt; {
        setSelectedOption(option);
        setIsOpen(false);
        if (selectedOption?.name === &quot;m-st&quot;) {
          props.setID(() =&gt;{
    
            
            props.setSysmexArray(() =&gt; [
              ...props.SysmexArray,
              [props.xAxis, props.yAxis, props.zAxis],
            ]);
          
            return&quot;m-st&quot;});
          }
        if (selectedOption?.name === &quot;CR10&quot;) {
          props.setID(() =&gt; {
            
            props.setCr10_no_7thArray(() =&gt; [
              ...props.cr10_no_7thArray,
              [props.xAxis, props.yAxis, props.zAxis],
            ]);
           
            return&quot;r-cr10&quot;});
        }
      };
    
      return (
        &lt;div className=&quot;relative pl-0&quot; ref={dropdownRef}&gt;
          &lt;button
            type=&quot;button&quot;
            className=&quot;flex items-center justify-between w-full px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500&quot;
            onClick={toggleDropdown}
          &gt;
            {selectedOption ? (
              &lt;&gt;
                {props.title}
                {console.log(`${selectedOption.name} : ${selectedOption.value}`)}
              &lt;/&gt;
            ) : (
              props.title
            )}
            &lt;svg
              className={`w-5 h-5 ml-2 transition-transform ${
                isOpen ? &quot;transform rotate-180&quot; : &quot;&quot;
              }`}
              viewBox=&quot;0 0 20 20&quot;
              fill=&quot;currentColor&quot;
              aria-hidden=&quot;true&quot;
            &gt;
              &lt;path
                fillRule=&quot;evenodd&quot;
                d=&quot;M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z&quot;
                clipRule=&quot;evenodd&quot;
              /&gt;
            &lt;/svg&gt;
          &lt;/button&gt;
          {isOpen &amp;&amp; (
            &lt;div className=&quot;absolute z-10 w-full mt-2 bg-white rounded-md shadow-lg&quot;&gt;
              &lt;ul className=&quot;py-1&quot;&gt;
                {props.options.map((option) =&gt; (
                  &lt;li
                    key={option.value}
                    className=&quot;flex flex-col justify-center items-center px-4 py-2 text-sm text-gray-700 cursor-pointer hover:bg-gray-100&quot;
                    onClick={() =&gt; handleOptionClick(option)}
                  &gt;
                    &lt;img
                      src={option.image}
                      height={100}
                      width={100}
                      alt={option.name}
                    /&gt;{&quot; &quot;}
                 
                    &lt;div className=&quot;text-center&quot;&gt;{option.name}&lt;/div&gt;
                  &lt;/li&gt;
                ))}
              &lt;/ul&gt;
            &lt;/div&gt;
          )}
        &lt;/div&gt;
      );
    };
    
    export default Dropdown;
    
    

    I've tried changing dependecy arrrays of useEffect, using useCallback to make sure it fire only what is got clicked but neither of them worked for me.

    答案1

    得分: 2

    Use option参数而不是selectedOption状态,否则您的函数将使用先前的selectedOption值。此外,我们不知道setID函数确切是做什么的,所以这只是一次尝试。但是,请尝试以下内容,看看是否有效。

    const handleOptionClick = (option: Option) => {
        setSelectedOption(option);
        setIsOpen(false);
        if (option?.name === "m-st") {
            props.setID(() => {
                props.setSysmexArray(() => [
                    ...props.SysmexArray,
                    [props.xAxis, props.yAxis, props.zAxis],
                ]);
                return "m-st";
            });
        }
        if (option?.name === "CR10") {
            props.setID(() => {
                props.setCr10_no_7thArray(() => [
                    ...props.cr10_no_7thArray,
                    [props.xAxis, props.yAxis, props.zAxis],
                ]);
                return "r-cr10";
            });
        }
    };
    
    英文:

    Use option argument instead of selectedOption state otherwise your function will use previous value of selectedOption. Also we don't know what setID function exactly does so this is a shot in dark. But try below and see if it works.

    const handleOptionClick = (option: Option) =&gt; {
        setSelectedOption(option);
        setIsOpen(false);
        if (option?.name === &quot;m-st&quot;) {
          props.setID(() =&gt;{
    
            
            props.setSysmexArray(() =&gt; [
              ...props.SysmexArray,
              [props.xAxis, props.yAxis, props.zAxis],
            ]);
          
            return&quot;m-st&quot;});
          }
        if (option?.name === &quot;CR10&quot;) {
          props.setID(() =&gt; {
            
            props.setCr10_no_7thArray(() =&gt; [
              ...props.cr10_no_7thArray,
              [props.xAxis, props.yAxis, props.zAxis],
            ]);
           
            return&quot;r-cr10&quot;});
        }
      };
    

huangapple
  • 本文由 发表于 2023年4月17日 18:40:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76034273.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定