25 + 5 Timer Not passing tests even though it works?

Ive been trying for ages to complete this but it just isnt working. People on stack-overflow keep closing my posts for help and it generally just won’t let me finish it even though the code is 100% functional in my eyes. Please help me figure out why the tests arent passing.

Link to my code: https://codepen.io/infinity_ninja1239/pen/XWZVORX

You are mutating state instead of using setState. I would start by fixing that.

1 Like

I will get back to you when I fix that. Thanks!

I’ve done that now but it still isnt passing some of the tests. I fixed what had broken because of it but now im stuck again.

You are still mutating the state in multiple places. At no point should you do this.state.someProp = 'some new value'

So for example, none of this this.state.sessionLength += 1; or this this.state.timeRemaining--;.

Search for this.state and correct all your state mutations to use setState instead.

When I do that the tests start to work a bit more as intended.

1 Like

I’ve completely ran through and made sure there is none left but now the increment and decrement buttons are late to update the time…

I would suggest you check the state before trying to change the break/session length in the state. So basically the same code as in updateBrkAndSesh should be wrapping setState calls instead.

1 Like

That was fun… somehow we can now set your times to -1 which made the tests run forever as the clock decrements.

When I was using React I found that state updates aren’t immediate, meaning if I did something like this, it would use the old value in the code instead of new values:

this.setstate({myvar: false})
if (this.state.myvar == true) { console.log("failure") }

OUTPUT: failure

The if line would run before the state updated… I read that its because the state can’t be changed until a new render is complete which is kicked off by changing the state, but it doesn’t stop and wait for that. A way around that is to do your logic, then when finished perform a state update… or pull the old values of the states into a local variable to use in your future logic:


myNewStateValue = false
if (myNewStateValue== true) { console.log("failure") }
this.setstate({myvar: myNewStateValue})

The way to handle it depends on what your code is attempting to do. Also, I see you are using state values to update your state values. If you remember right from the lessons you should do that with a callback function, not directly.

this.setstate( state => ({example = state.example + " updated example"}))

FROM YOUR CODE:
this.setState({ breakLength: this.state.breakLength - 1 });

Although unless you are making a lot of changes at the same time, or multiple users are involved, it may not cause an issue with a smaller app like this, but probably should get into the habit. Hope this all makes sense.

1 Like

So what your saying is that i should set like variables and then after all the logic i should update the state?

Well, there are many ways to overcome this issue. Basically what you need to avoid is trying to use your state immediately after setting it in your code… basically.

this.setstate( { message : "Task Complete!!!" } );
console.log (this.state.message);

Will not print “Task Complete!!!” to console, because the state hasn’t updated yet… it will update after a rerender is completely. So if you need to do something like this, this would probably be better.

let newMessage = "Task Complete!!!";
console.log(newMessage);
this.setstate( { message : newMessage } );

Basically in your inc/dec code it seemed you were using the state to change the state then using that new state to verify the state, all before it ever got a change to update. I’d suggest not using the state as a standard variable, but as a place to post the results of your computations.

Also, I’m not really a React expert… maybe a code veteran on here has a more elegant solution.

1 Like

Right so for example

let message = this.state.message
message = message.concat("Helllo")
document.getElementById("messageBox").innerHTML = message;
this.setstate( { message : message } );

is the best way to use it?

I can’t for sure tell you that’s the “best” way to use it… but the above script will work without generating any errors or incorrect values.

either way it doesnt work as updateBrkAndSesh() uses logic immediately is there any way to force render it?

Yeah, updateBrkAndSesh seems to do exactly what was warned against, immediately using state values you just changed… I’m guessing the Javascript will execute faster than the render… maybe someone knows a way to force an update of the state before any further lines of code execute… I just avoided doing it…

Quick question… why are you updating your DOM elements with vinella Javascript?

document.getElementById("timer-label").innerHTML = this.state.timerType;

Wasn’t one of the main purposes of REACT that it draws your HTML elements in its render() function depending on the value of the state? Thats why it re-renders when the state is changed, so that it can redraw the components as you specify. That should negate the need to be doing these manual changes.

Actually, you are also doing it in your render function… so why are you re-doing it with your updateBrkAndSesh() function?

You’re doing this:
document.getElementById("timer-label").innerHTML = this.state.timerType;

And then your render function does this:
<div id="timer-label">{this.state.timerType}</div>

It seems like most of your updateBrkAndSesh() function is entirely redundant, doing what your render function was going to do anyway… wouldn’t know that 100% though without a deep dive.

wait so i don’t need to set it then?

Oh yes that works and done that now the increment and decrement works but now when the session ends the break “starts” but it uses the sessionLength.

wait fixed that too oops its bcs i used a condition that flipped it twice…

now it says that the timer doesnt reach zero when infact it does.

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.