当前位置: 首页 > 知识库问答 >
问题:

理解use效应()和useState()钩子的行为

夏飞跃
2023-03-14

因此,我有一些代码并没有像预期的那样工作。当前焦点是在父组件上使用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。我可以通过删除空[]作为useffect中的第二个参数来解决这个问题。但是,我希望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)
  }
 },[]);

我对解决方案并不感兴趣,我真正感兴趣的是理解useffect()和useState()钩子在这种情况下是如何工作的。

共有1个答案

袁帅
2023-03-14

嘿,使用效果钩子可能有点混乱。但思考的方式是

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值传递给focus 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]);

希望有帮助!

 类似资料:
  • 我在React hook中遇到了一些非常奇怪的行为。在下面的代码中(https://codesandbox.io/s/purple-bush-nb5uy?file=/src/index.js): 单击时,我们在控制台中获得以下序列: 我希望: 因为我认为如果React找到setter并在重新渲染后执行以下代码,它会立即重新渲染。此外,我的React应用程序也是如此: 当运行以及值与状态变量的内容不

  • 我第一次面对的问题很小。我试图使用一个简单的useState,但出于某种原因,我不明白为什么React会给我一个错误,不管我想做什么--没有什么能修复它。 这是错误的图像:错误描述: 错误:无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一:1.React和呈现器(例如React DOM)2的版本可能不匹配。你可能违反了钩子3的规则。在同一个应用程序中可能有多个React副

  • 案例1: 案例2: 在案例1中,当我试图使用内部循环更新当前状态时,当前状态没有更新。但是,当我在用例2中单独使用useffect()之外的循环并创建一个数组,然后分配给当前状态时,当前状态正在更新。 这背后的原因是什么?为什么在案例1中当前状态没有更新?

  • 钩子和行为 ThinkPHP中的行为是一个比较抽象的概念,你可以把行为想象成在应用执行过程中的一个动作。在框架的执行流程中,例如路由检测是一个行为,静态缓存是一个行为,用户权限检测也是行为,大到业务逻辑,小到浏览器检测、多语言检测等等都可以当做是一个行为,甚至说你希望给你的网站用户的第一次访问弹出Hello,world!这些都可以看成是一种行为,把这些行为抽离出来的目的是为了让你无需改动框架和应用

  • 我有一个应用程序,当试图从异步函数内部使用useState钩子时出错。 这里是App.js 这里是错误 元素类型无效:需要字符串(对于内置组件)或类/函数(对于复合组件),但得到:未定义。您可能忘记了从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。 检查的渲染方法。 index.js package.json 更新错误-删除!认证 元素类型无效:需要字符串(对于内置组件)或类/函数

  • 我正努力让你去工作。以下是功能组件: 我称之为: 我得到一个错误,如下所示: 错误:无效的钩子调用。钩子只能在函数组件的主体内部调用。发生这种情况的原因如下:1。React和渲染器(如React DOM)2的版本可能不匹配。你可能违反了Hooks 3的规则。同一应用程序中可能有多个React副本。 我已经调试并确认我使用的是单一版本。也许我使用状态钩子不正确? 这里是我调用自定义钩子的地方: