尝试在React中创建Pomodoro,但无法正确传递道具

时间:2019-12-24 03:00:25

标签: javascript reactjs react-props

这是我在这里的第一个帖子!

我正在React中创建一个 Pomodoro 。我的目标很简单。我正在创建一个Pomodoro时钟,能够在JavaScript中成功完成此操作,但是具有React组件体系结构。但是我遇到了一些问题。

所以我的App组件有3个子级:SessionTimerBreak

应用组件

    let [fromSession, setFromSession] = useState();
    let [isSession, setIsSession] = useState();
    let [fromBreak, setFromBreak] = useState();
    let [isBreak, setIsBreak] = useState();

    const fromSessionFunction = w => {
        setFromSession(w);
    }

    const sessionTrueOrNot = x => {
        setIsSession(x);
    }

    const fromBreakFunction = y => {
        setFromBreak(y);
    }

    const breakTrueOrNot = z => {
        setIsBreak(z);
    }

    if(isBreak === true) { 
        isSession = false;
    }

    if (isSession === true) {
        isBreak = false;
    }

    console.log('from App', isSession, isBreak)

    return (
        <div className='app-background center'>
            <h1>Pomodoro Timer</h1>
            <div className='flex'>
                <Session sessionFunctionFromApp={fromSessionFunction} sessionTrueOrNot={sessionTrueOrNot}/>
                <Timer sessionFromApp={fromSession} isSessionFromApp={isSession} breakFromApp={fromBreak} isBreakFromApp={isBreak}/>
                <Break breakFunctionFromApp={fromBreakFunction} breakTrueOrNot={breakTrueOrNot}/>
            </div>
        </div>
    )
}

export default App;

会话组件

    let [sessionTime, setSessionTime] = useState(25);
    let [sessionTrue, setSessionTrue] = useState();

    const decreaseSessionFunction = () => {
        setSessionTime(sessionTime -= 1);
        setSessionTrue(true);
    }

    const increaseSessionFunction = () => {
        setSessionTime(sessionTime += 1);
        setSessionTrue(true);
        console.log(sessionTrue);
    }

    useEffect(() => {
        setSessionTrue(true);
    }, []);

    sessionFunctionFromApp(sessionTime);
    sessionTrueOrNot(sessionTrue);

    return (
        <div>
            <h3>Session</h3>
            <p>{sessionTime}:00</p>
            <button className='ui purple basic button' onClick={() => decreaseSessionFunction()}>-</button>
            <button className='ui purple basic button' onClick={() => increaseSessionFunction()}>+</button>
        </div>
    )
}

export default Session;

计时器组件

    let name, display;

    if(isSessionFromApp) {
        name = 'Timer for Session';
        display = sessionFromApp;
    }

    if(isBreakFromApp) {
        name = 'Timer for Break';
        display = breakFromApp;
    }

    return (
        <div>
            <h2>{name}</h2>
            <p id='big-font'>{display}:00</p>
            <button className='ui blue basic button'>Start</button>
            <button className='ui blue basic button'>Stop</button>
            <button className='ui blue basic button'>Restart</button>
        </div>
    )
}

export default Timer;

中断组件

    let [breakTime, setBreakTime] = useState(10);
    let [breakTrue, setBreakTrue] = useState();

    const decreaseBreakFunction = () => {
        setBreakTime(breakTime -= 1);
        setBreakTrue(true);
    }

    const increaseBreakFunction = () => {
        setBreakTime(breakTime += 1);
        setBreakTrue(true);
        console.log(breakTrue);
    }

    useEffect(() => {
        setBreakTrue(false)
    }, []);

    breakFunctionFromApp(breakTime);
    breakTrueOrNot(breakTrue);

    return (
        <div>
            <h3>Break</h3>
            <p>{breakTime}:00</p>
            <button className='ui violet basic button' onClick={() => decreaseBreakFunction()}>-</button>
            <button className='ui violet basic button' onClick={() => increaseBreakFunction()}>+</button>
        </div>
    )
}

export default Break;

好吧,实际上,我唯一想做的就是从App像现在这样console.log时,它会打印出truefalse这很好。

我希望Session在默认情况下为true,而Break为false。所以,我想要的是单击Break的+时,尽管App中的console.log更改为false true。从Break组件的第15行说是false。

为什么会这样?

如果这是假的,那么应用程序怎么会说假的真的?

最后,当我单击Session的+时,Session组件的第15行再次显示为true,而App打印的结果为false。

感谢您的阅读,非常感谢您的帮助,我了解我的代码反映出我是一个初学者。

1 个答案:

答案 0 :(得分:1)

您看到BreakApp说出关于看似相同值breakTrue的冲突。但实际上它们是两个价值。这是因为setState()是一个异步函数。您不能期望它会立即更改其状态。

En bref,您的代码执行顺序如下:

[PSEUDO CODE]

1. Break: setBreakTrue(true)
// issue an async update command, doesn't take effect yet.

2. Break: console.log(breakTrue)
// sync func, instant effect, so you see the old value `false` before previous command

3. App: console.log('from App', isBreak)
// exec in the re-render cycle triggered by 1st command, thus reflects the new value `true`.

在此附上demoboard。检查Break文件ln:22,我添加了:

useEffect(() => console.log('breakTrue (async):', breakTrue))

console.log包装在useEffect内,因此它在执行 setState命令后执行,因此您将看到{{ 1}}成为breakTrue


附带的是对该应用程序的重写:

https://frontarm.com/demoboard/?id=aa46b63b-a020-4041-b8a8-14c2174c647e