React hooks使用

hec9527
  • 82

我想在input输入框中按Enter直接提交输入类容(调用一个外部dispatch),然后再清空输入框,但是现在的结果是,可以清空输入框,但是在handlePress函数里面死活获取不到name,每次的值都是''。如果把name添加到useEffect的依赖,又会重复添加事件绑定,并且handlePress函数也会多次执行。
我尝试用useCallback包裹handlePress函数也无济于事,到底怎样才能实现我想要的效果呢

const Input = ({ addName }) => {
  const [name, setName] = useState('');
  const inputRef = React.createRef();

  const handlePress = e => {
    if (e.key === 'Enter') {
      console.log('name:', name);
      addName({ name });
      setName('');
    }
  };

  useEffect(() => {
    inputRef.current?.addEventListener('keydown', e => handlePress(e));
    return () => {
      inputRef.current?.removeEventListener('keydown', e => handlePress(e));
    };
  }, []);

  return (
    <div className='input-wrap'>
      <input
        ref={inputRef}
        value={name}
        type='text'
        className='input'
        placeholder='Please input your something'
        onChange={e => setName(e.target.value)}
      />
    </div>
  );
};
回复
阅读 1.3k
2 个回答

方法1,将handlePress作为input的属性传入,将其接入组件的更新流程,此时react会保证handlePress闭包内捕获的name始终是最新值

const Input = ({ addName }) => {
  const [name, setName] = useState("");
  const inputRef = React.createRef();

  const handlePress = (e) => {
    if (e.key === "Enter") {
      console.log("name:", name);
      addName({ name });
      setName("");
    }
  };

  return (
    <div className="input-wrap">
      <input
        ref={inputRef}
        value={name}
        type="text"
        className="input"
        placeholder="Please input your something"
        onChange={(e) => setName(e.target.value)}
        onKeyDown={handlePress}
      />
    </div>
  );
};

方法2,手动用ref保存最新的handlePress然后通过他调用handlePress


const Input = ({ addName }) => {
  const [name, setName] = useState("");
  const inputRef = React.createRef();
  const latestFunc = useRef();

  const handlePress = (e) => {
    if (e.key === "Enter") {
      console.log("name:", name);
      addName({ name });
      setName("");
    }
  };

  latestFunc.current = handlePress;

  useEffect(() => {
    inputRef.current?.addEventListener("keydown", (e) => latestFunc.current(e));
    return () => {
      inputRef.current?.removeEventListener("keydown", (e) =>
        latestFunc.current(e)
      );
    };
  }, []);

  return (
    <div className="input-wrap">
      <input
        ref={inputRef}
        value={name}
        type="text"
        className="input"
        placeholder="Please input your something"
        onChange={(e) => setName(e.target.value)}
      />
    </div>
  );
};

需要添加依赖项

  useEffect(() => {
    inputRef.current?.addEventListener('keydown', e => handlePress(e));
    return () => {
      inputRef.current?.removeEventListener('keydown', e => handlePress(e));
    };
  }, [name]);
宣传栏