为什么在 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}));
};

物有所值...