我面临的问题与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
。
由于大多数堆栈溢出答案都表明使用钩子的状态更新是异步的,因此我尝试使用setTimeout
我认为我们可以使用async-await
,但这是错误的方法
我尝试更新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
中的其他两种方法
我是指错误类型的问题,还是这是反应中的常见现象?
愿意在需要时提供更多信息
我添加了console.log()
,因为我在进行操作之后进行了使用状态变量值的状态更改。
使用React开发工具,我看到状态正在更新并且几乎是立即更新。问题在于按下按钮会导致在实际代码中弹出一个对话框,该对话框的组件将状态用于其他逻辑,因此我收到一个错误,指出该状态仍然为空
答案 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中使用花括号直接调用它。