[英]State isn't updated on handler call from child to parent
I have a parent component PlannerDetails
and a child component PlannerDetailsFooter
.我有一个父组件
PlannerDetails
和一个子组件PlannerDetailsFooter
。 Now when I click the button {props.emailConfig.buttonText}
doesn't update with string Send Now
, the boolean does though.现在,当我单击按钮时
{props.emailConfig.buttonText}
不会更新为字符串Send Now
,但 boolean 会更新。
// PlannerDetails
import {useState} from "react";
import PlannerDetailsHead from "./PlannerDetailsHead";
import PlannerDetailsBody from "./PlannerDetailsBody";
import PlannerDetailsFooter from "./PlannerDetailsFooter";
const PlannerDetails = (props) => {
const [emailConfig, setEmailConfig] = useState(
{
'email': '',
'isSent': false,
'isHidden': true,
'buttonText': 'Send via Email'
}
)
const emailHandler = (event) => {
if (event.id === "mail-button") {
setEmailConfig({...emailConfig, isHidden: false})
setEmailConfig({...emailConfig, buttonText: 'Send Now'})
} else {
setEmailConfig(event.target.value)
}
}
return (
<div className="details-wrapper relative h-full">
<PlannerDetailsHead {...props}/>
<PlannerDetailsBody {...props}/>
<PlannerDetailsFooter {...props} emailConfig={emailConfig} emailHandler={emailHandler}/>
</div>
)
}
export default PlannerDetails
// PlannerDetailsFooter
import {TextField} from "@mui/material";
const PlannerDetailsFooter = (props) => {
return (
<div className="details-footer w-full p-4 bottom-0 absolute border-t-1">
{props.emailConfig.isHidden ? null :
<TextField
id="email-input"
label="Applicant's E-Mail"
variant="outlined"
required={true}
sx={{
width: '200px',
marginRight: '12px',
}}
value={props.emailConfig.email}
onChange={props.emailHandler}
/>}
<button id="mail-button"
className="send-mail p-2 bg-sx-pink rounded-md shadow-lg text-sx-purple-dark-soft"
onClick={props.emailHandler}
>{props.emailConfig.buttonText}</button>
</div>
)
}
First you'll want to debug to confirm whether this condition is true or not:首先,您需要调试以确认此条件是否成立:
if (event.id === "mail-button")
Because if it's not then it looks like this is going to clobber your state object entirely:因为如果不是,那么看起来这将完全破坏您的 state object:
setEmailConfig(event.target.value)
So it's not really clear at all what state update you want to make in that else
block.因此,您根本不清楚您想在
else
块中进行什么 state 更新。 It should probably look like your other state updates, at least structurally:它应该看起来像您的其他 state 更新,至少在结构上是这样:
setEmailConfig({...emailConfig, someProp: 'some value'})
But aside from that, this is incorrect:但除此之外,这是不正确的:
setEmailConfig({...emailConfig, isHidden: false})
setEmailConfig({...emailConfig, buttonText: 'Send Now'})
Only one of these will be applied, because they're both updating different things and state updates are batched and processed asynchronously.只会应用其中一个,因为它们都在更新不同的内容,并且 state 更新是异步批处理和处理的。 So whichever one of these occurs second will overwrite the changes made by the first one.
因此,无论其中哪一个发生在第二个,都会覆盖第一个所做的更改。 (They will probably be executed in order, but I don't know if React guarantees that. And in any even, you shouldn't rely on that.)
(它们可能会按顺序执行,但我不知道 React 是否保证这一点。无论如何,你不应该依赖它。)
Just perform one state update here:只需在这里执行一次state 更新:
setEmailConfig({...emailConfig, isHidden: false, buttonText: 'Send Now'})
You can perform multiple state updates, making use of the previous updates in the same batch by supplying a callback.您可以执行多个 state 更新,通过提供回调在同一批次中使用以前的更新。 For example:
例如:
setEmailConfig(prev => {...prev, isHidden: false});
setEmailConfig(prev => {...prev, buttonText: 'Send Now'});
But in this case that's kind of overkill.但在这种情况下,这有点矫枉过正。 You'd use that in more complex logic where it's possible that you might have multiple separate things to update.
你会在更复杂的逻辑中使用它,在这种情况下你可能有多个单独的东西要更新。 But honestly in the majority of cases all you want to do is define the new state and call the setter with that new state, so one state update.
但老实说,在大多数情况下,您要做的就是定义新的 state 并使用新的 state 调用 setter,这样一个 state 更新。
There is a mistake in your handler function.您的处理程序 function 中存在错误。
1. Especially, this is incore: setEmailConfig(event.target.value)
1. 特别是,这是核心:
setEmailConfig(event.target.value)
Because emailConfig
is an object, but you are trying to set string
value.因为
emailConfig
是一个 object,但您正在尝试设置string
值。
2. Please use setState
function with previous state
. 2. 请使用
setState
function 和之前state
。
Could you try as follows?你可以尝试如下吗?
const emailHandler = (event) => {
if (event.id === "mail-button") {
setEmailConfig(prev=> ({
...prev,
isHidden: false,
buttonText: 'Send Now'
}))
} else {
setEmailConfig(prev=> ({
...prev,
email: event.target.value
}))
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.