因此,我有这段代码无法正常工作。当前焦点已在父组件上使用useState()设置,因此它是一个状态变量。但是,当父项中的currentFocus值更改时,此处的focus变量本身不会更新。我本来希望重新渲染父组件,然后重新渲染该组件将导致foucs值发生变化。

import React, { useRef, useEffect, useState } from 'react';
const CookieDetails = props => {
  const {
    name,
    cost,
    value,
    numOwned,
    onMouseClick,
    cookieId,
    currentFocus,
  } = props;

  let cookieInfoRef = useRef(null);
  //My focus doesnt change even if I change currentFocus in parent component
  const [focus, setFocus] = useState(currentFocus);

  useEffect(() => {
    console.log('currentFocus', currentFocus);
    console.log('focus', focus);
    console.log('cookieID', cookieId);
    if (cookieInfoRef.current && cookieId === focus) {
      console.log('current', cookieInfoRef.current);
      cookieInfoRef.current.focus();
    }
  }, [focus]);

  return (
    <React.Fragment>
      <button
        onClick={onMouseClick}
        ref={cookieId === focus ? cookieInfoRef : null}
      >
        <h3>{name}</h3>
        <p>Cost:{cost}</p>
        <p>Value:{value}</p>
        <p>Owned:{numOwned}</p>
      </button>
    </React.Fragment>
  );
};

export default CookieDetails;


现在,我可以执行以下操作来解决此问题,

import React, { useRef, useEffect, useState } from 'react';
const CookieDetails = props => {
  const {
    name,
    cost,
    value,
    numOwned,
    onMouseClick,
    cookieId,
    currentFocus,
  } = props;

  let cookieInfoRef = useRef(null);

  useEffect(() => {
    console.log('currentFocus', currentFocus);
    console.log('cookieID', cookieId);
    if (cookieInfoRef.current && cookieId === currentFocus) {
      console.log('current', cookieInfoRef.current);
      cookieInfoRef.current.focus();
    }
  });

  return (
    <React.Fragment>
      <button
        onClick={onMouseClick}
        ref={cookieId === currentFocus ? cookieInfoRef : null}
      >
        <h3>{name}</h3>
        <p>Cost:{cost}</p>
        <p>Value:{value}</p>
        <p>Owned:{numOwned}</p>
      </button>
    </React.Fragment>
  );
};

export default CookieDetails;


但是我只想在focus / currentFocus更新时而不是在每次渲染后运行useEffect挂钩。那么为什么会这样呢?我在这里缺少了解什么。

我以前也注意到,如果您这样做,handleStuff函数将始终使用初始值100(因此始终为100 + 10),而不是每次按键都增加10。我可以通过删除空[]作为useEffect中的第二个参数来解决此问题。但是,我预计handleStuff仍将更新为最新值,因为eventListner已在初始渲染中添加,并且在第二次按下时应将10增加到110而不是100,但它仍使用初始状态值100代替。为什么必须清除旧的侦听器并每次都添加一个新侦听器才能起作用?

[value, setValue] = useState(100)

handleStuff = (event) => {
 setValue(value+10)
}

useEffect(() => {
  window.addEventListener('keydown', handleStuff)
  return () => {
    window.removeEventListener('keydown', handleStuff)
  }
 },[]);


我对解决方案并没有真正的兴趣,对了解在这种情况下useEffect()和useState()钩子如何工作真的很了解。

最佳答案

嘿,useEffect挂钩可能有点混乱。
但是思考的方法是

useEffect(() => {
  // Called every render
})

useEffect(() => {
  // Called on first render
}, [])

useEffect(() => {
  // Called when x y & z updates
}, [x, y, z])


问题是您没有在代码中监听currentFocus更新。

useEffect(() => {
  // Called when focus updates
}, [focus]);

useEffect(() => {
  // Called when props.currentFocus & focus updates
}, [props.currentFocus, focus]);


现在解释一下您的困惑:

// My focus doesnt change even if I change currentFocus in parent component
const [focus, setFocus] = useState(currentFocus);


当您在此处传递currentFocus时,将currentFocus值传递给焦点useState的唯一时间是在第一个渲染上。因此,您需要侦听currentFocus更新,然后设置新焦点,该焦点应该可以按您希望的方式工作!

// Focus set to props.currentFocus on first render
const [focus, setFocus] = useState(currentFocus);

useEffect(() => {
  // Update focus
  setFocus(props.currentFocus)
}, [props.currentFocus])

useEffect(() => {
  // currentFocus will be the same as focus now
  console.log('currentFocus', currentFocus);
  console.log('focus', focus);
  console.log('cookieID', cookieId);
  if (cookieInfoRef.current && cookieId === focus) {
    console.log('current', cookieInfoRef.current);
    cookieInfoRef.current.focus();
  }
}, [focus]);


希望有帮助!

关于javascript - 了解useEffect()和useState() Hook 的行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60628301/

10-09 18:13