为什么在 onClick 事件中只执行了两个函数中的一个
Why only 1 function out of two gets executed in onClick event
我正在构建一个简单的 React 应用程序,它旨在传递几个负责更新父组件中相同状态对象的函数,但由于某种原因,当由中的 onClick 事件触发时,只有两个函数中的一个被执行一个子组件或者至少看起来是这样,让我给你看一些代码:
子组件:
<button id='but2' onClick={()=>{
props.isBeginner(true);
props.nextStep(2)
}}
className={classes.chooseButton} >Choice number 1</button>
父组件函数:
isBeginner(b){
setUser({...user,first_timer:b})}
nextStep =(step)=>{
setUser({...user,setup_step:step})}
在子组件和父组件之间,有一个中间组件负责对要渲染的子组件进行排序,它通过
开关运算符:
switch(step){
case 1 :{return <StepOne user={props.user} nextStep={props.nextStep}
isBeginner={props.isBeginner} />};
break;
case 2 :{return <StepTwo whatMedium={props.whatMedium} user=
{props.user} nextStep={props.nextStep}/>}
break;
case 3 :{return <StepThree user={props.user} nextStep=
{props.nextStep}/>}
break;
case 4 :{return <StepFourth nextStep={props.nextStep}/>}
break;
default:{<StepOne isBeginner={props.isBeginner} nextStep={
props.nextStep}/>}
}
为什么我不能使用两个不同的函数(传递给子组件)更新父组件的状态来更新同一(状态)对象的不同值?
两个函数都执行了,但是似乎只执行了其中一个,因为每个函数都使用了in-scope user
状态成员,它是陈旧 第一次更新完成后。所以第二次更新不包括第一次更新的变化。
当基于现有状态更新状态时,为避免使用陈旧信息进行更新,最好使用状态的回调形式 setter:
isBeginner(b){
setUser(user => ({...user, first_timer: b}));
}
// ...
nextStep = (step) => {
setUser(user => ({...user, setup_step: step}));
};
这样,每个状态更新都使用 up-to-date 状态值完成。
这是一个更简单的例子:
const {useState} = React;
const classes = {
chooseButton: "",
};
const Child = (props) => {
return <button
id='but2' onClick={() => {
props.isBeginner(true);
props.nextStep(2)
}}
className={classes.chooseButton}
>
Choice number 1
</button>;
};
const Wrong = () => {
const [user, setUser] = useState({
first_timer: false,
setup_step: 1,
});
const isBeginner = (b) => {
setUser({...user,first_timer:b});
};
const nextStep = (step) => {
setUser(({...user,setup_step:step}));
};
return <div>
<h2>Wrong</h2>
<div>first_timer: {String(user.first_timer)}</div>
<div>step: {user.setup_step}</div>
<Child isBeginner={isBeginner} nextStep={nextStep} />
</div>;
};
const Right = () => {
const [user, setUser] = useState({
first_timer: false,
setup_step: 1,
});
const isBeginner = (b) => {
setUser(user => ({...user, first_timer: b}));
};
const nextStep = (step) => {
setUser(user => ({...user, setup_step: step}));
};
return <div>
<h2>Right</h2>
<div>first_timer: {String(user.first_timer)}</div>
<div>step: {user.setup_step}</div>
<Child isBeginner={isBeginner} nextStep={nextStep} />
</div>;
};
ReactDOM.render(
<div>
<Wrong />
<hr />
<Right />
</div>,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
旁注:我希望一个名为 nextStep
的函数能够处理前进到下一步本身,而不是接受步骤值的参数。例如:
nextStep = () => {
setUser(user => ({...user, setup_step: user.setup_step + 1}));
};
物有所值...
我正在构建一个简单的 React 应用程序,它旨在传递几个负责更新父组件中相同状态对象的函数,但由于某种原因,当由中的 onClick 事件触发时,只有两个函数中的一个被执行一个子组件或者至少看起来是这样,让我给你看一些代码:
子组件:
<button id='but2' onClick={()=>{
props.isBeginner(true);
props.nextStep(2)
}}
className={classes.chooseButton} >Choice number 1</button>
父组件函数:
isBeginner(b){
setUser({...user,first_timer:b})}
nextStep =(step)=>{
setUser({...user,setup_step:step})}
在子组件和父组件之间,有一个中间组件负责对要渲染的子组件进行排序,它通过 开关运算符:
switch(step){
case 1 :{return <StepOne user={props.user} nextStep={props.nextStep}
isBeginner={props.isBeginner} />};
break;
case 2 :{return <StepTwo whatMedium={props.whatMedium} user=
{props.user} nextStep={props.nextStep}/>}
break;
case 3 :{return <StepThree user={props.user} nextStep=
{props.nextStep}/>}
break;
case 4 :{return <StepFourth nextStep={props.nextStep}/>}
break;
default:{<StepOne isBeginner={props.isBeginner} nextStep={
props.nextStep}/>}
}
为什么我不能使用两个不同的函数(传递给子组件)更新父组件的状态来更新同一(状态)对象的不同值?
两个函数都执行了,但是似乎只执行了其中一个,因为每个函数都使用了in-scope user
状态成员,它是陈旧 第一次更新完成后。所以第二次更新不包括第一次更新的变化。
当基于现有状态更新状态时,为避免使用陈旧信息进行更新,最好使用状态的回调形式 setter:
isBeginner(b){
setUser(user => ({...user, first_timer: b}));
}
// ...
nextStep = (step) => {
setUser(user => ({...user, setup_step: step}));
};
这样,每个状态更新都使用 up-to-date 状态值完成。
这是一个更简单的例子:
const {useState} = React;
const classes = {
chooseButton: "",
};
const Child = (props) => {
return <button
id='but2' onClick={() => {
props.isBeginner(true);
props.nextStep(2)
}}
className={classes.chooseButton}
>
Choice number 1
</button>;
};
const Wrong = () => {
const [user, setUser] = useState({
first_timer: false,
setup_step: 1,
});
const isBeginner = (b) => {
setUser({...user,first_timer:b});
};
const nextStep = (step) => {
setUser(({...user,setup_step:step}));
};
return <div>
<h2>Wrong</h2>
<div>first_timer: {String(user.first_timer)}</div>
<div>step: {user.setup_step}</div>
<Child isBeginner={isBeginner} nextStep={nextStep} />
</div>;
};
const Right = () => {
const [user, setUser] = useState({
first_timer: false,
setup_step: 1,
});
const isBeginner = (b) => {
setUser(user => ({...user, first_timer: b}));
};
const nextStep = (step) => {
setUser(user => ({...user, setup_step: step}));
};
return <div>
<h2>Right</h2>
<div>first_timer: {String(user.first_timer)}</div>
<div>step: {user.setup_step}</div>
<Child isBeginner={isBeginner} nextStep={nextStep} />
</div>;
};
ReactDOM.render(
<div>
<Wrong />
<hr />
<Right />
</div>,
document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
旁注:我希望一个名为 nextStep
的函数能够处理前进到下一步本身,而不是接受步骤值的参数。例如:
nextStep = () => {
setUser(user => ({...user, setup_step: user.setup_step + 1}));
};
物有所值...