声明既未从useState更新,也未在useState

时间:2020-10-13 04:36:54

标签: javascript reactjs react-hooks react-functional-component

我面临的问题与this question

中几乎相同

代码有点太多,所以我做了一个简化版的问题。 (如果我这样做有误,请原谅我

基本上,我有一个主组件和一个子组件

主要组件

import React {useState} from 'react'
import SubComponent from './subcomponent';

const Main = (props) => {
  const [state, setState] = useState(null);
  const updateStateFunction = (data) => {
    const newState = data
    console.log(state)
    setState(newState)
    console.log(state)
  }

  return (
    <div>
      <SubComponent
        updateStateFunction = {updateStateFunction}
      />
    </div>
  )
}


export default Main;

子组件

import React {useState} from 'react'
const SubComponent = ({updateStateFunction}) => {
  return (
    <div>
      <button
        onClick={() => updateStateFunction("Something new")}
      >       
      </button>
    </div>
  )
}
export default SubComponent;

两个控制台日志都给出null

我试图解决的问题:

  1. 由于大多数堆栈溢出答案都表明使用钩子的状态更新是异步的,因此我尝试使用setTimeout

  2. 我认为我们可以使用async-await,但这是错误的方法

  3. 我尝试更新useEffect内的状态,但要点是没有任何内容被重做。这是因为要更新的变量从不属于输出的一部分,而是对辅助变量进行排序以进行进一步的操作。 我这样做的方法是使用the solution in the above refereced question

const Main = (props) => {

  /*Debugging*/
  let newState = null
  useEffect(()=>{
    console.log("useEffect called")
    setState(newState)
  }, [newState])
  /*Debugging*/

  const [state, setState] = useState(null);
  const updateStateFunction = (data) => {
    newState = data
    console.log(state)
    setState(newState)
    console.log(state)
  }

  return (
    <div>
      <SubComponent
        updateStateFunction = {updateStateFunction}
      />
    </div>
  )
}

我虽然由于甚至没有执行useEffect钩子,所以我没有尝试the solution

中的其他两种方法

我是指错误类型的问题,还是这是反应中的常见现象?

愿意在需要时提供更多信息


编辑:
  1. 我添加了console.log(),因为我在进行操作之后进行了使用状态变量值的状态更改。

  2. 使用React开发工具,我看到状态正在更新并且几乎是立即更新。问题在于按下按钮会导致在实际代码中弹出一个对话框,该对话框的组件将状态用于其他逻辑,因此我收到一个错误,指出该状态仍然为空

3 个答案:

答案 0 :(得分:1)

我不确定let newState = null与引用的问题中的任何答案有什么关系,因此要清楚一点,这是直接应用已接受答案的方式:

const Main = (props) => {
  const [state, setState] = useState(null);
  const updateStateFunction = (data) => { setState(data) }

  useEffect(() => { console.log(state) }, [state])

  return <SubComponent updateStateFunction = {updateStateFunction} />
}

但是,如果状态不用于屏幕上呈现的任何内容,则没有任何改变的意义-如果Reacts未检测到返回值的任何变化,则它可能不会将任何更改提交给DOM。优化,因此在这种情况下它可能不会运行任何useEffect

我建议使用React Dev Tools检查组件的当前状态。

此外,console.log基本上是唯一不需要出现在useEffect内部的副作用。如果直接在render函数中,它将在调用render函数时执行,并且不依赖于React将更改提交到DOM ...

请注意,我对引用问题的回答中的第一条建议并未将console.log包装到useEffect中,再次说明一下,这是将如何直接应用该建议的方法:

const Main = (props) => {
  const [state, setState] = useState(null);
  const updateStateFunction = (data) => { setState(data) }

  console.log(state)

  return <SubComponent updateStateFunction = {updateStateFunction} />
}

答案 1 :(得分:0)

状态设置是异步的。 异步函数将与其他指令并行(很好)执行。您可以在返回功能之前使用console.log状态来知道新的输出,而不是在设置状态后使用console.logging

您的第一个实现没有任何问题。无需在此处使用useEffect

import React {useState} from 'react'
import SubComponent from './subcomponent';

const Main = (props) => {
  const [state, setState] = useState(null);
  const updateStateFunction = (data) => {
    setState(data)
  }
  
  // try console logging here
  console.log(state)
  return (
    <div>
      <SubComponent
        updateStateFunction = {updateStateFunction}
      />
    </div>
  )
}


export default Main;

这样想,只要设置了状态,包含该状态的函数就会刷新并重新运行。您可以在函数中的任何位置console.log以获得新状态。

答案 2 :(得分:0)

即使在console.log()显示null上您看到devtools中的状态更改,也可以使用react devtools进行调试。原因是状态更新是异步的。

如果您仍想使用console.log()调试react应用,请在return语句之前甚至在jsx中使用花括号直接调用它。