I appreciate all the effort put in the video. Is it me or there was someone else that didn't really understand still? Ugh, I was just coding along with question marks in my head.
Just completed, thank you for the great tutorial. Wasn't a beginner project in my opinion due to the amount of complex logic implemented in this one. Glad I was able to follow along and complete this with you. I was expecting this to take me about 2 hours to finish but instead took me like 4-5 hours, just so that I could make sure I could understand everything that was going on.
Thanks so much Kyle, this was an awesome project to start with. Just two things I noticed, first as Ninjashot mentioned, there is a step missing in the tutorial and that is adding "state" in front of currentOperand when creating ADD.DIGIT case. This should look like this: return { ...state, currentOperand:`${state.currentOperand || ""}${payload.digit}`, } And another bug I noticed while playing with the calculator and testing it, is that the app would crash when pressing "." with no digits there. This can be easily solved by adding the following line on top of the other If statement you have for the "." case on payload digit: This should look like this: if (payload.digit === "." && state.currentOperand == null) { return state } if (payload.digit === "." && state.currentOperand.includes(".")) { return state } Also I checked that all the calculators I have when pressing AC a "0" is displayed, so if you want to add that behaviour, just change the ACTIONS.CLEAR case to this: case ACTIONS.CLEAR: return { ...state, currentOperand: "0", previousOperand: null, operation: null } It should work fine after that. I appreciate the hard work it took for you to share this with us :)
@@mdmustaqahmed5391 Hi Mustaq, not sure of which part you’re talking about, but can you please comment what error is thrown? Usually it tells you which line of code is the one causing the issue, it could potentially be something else in your code
Thank you Marco, this was very helpful. May i suggest a change to your: if (payload.digit === "." && state.currentOperand == null) { return state } After refreshing the application, the currentOperand is null and if you press "." it does not immediately start a "0.XXXX" with your suggestion above, so I modified your suggestion to: if (payload.digit === "." && state.currentOperand == null) { return { ...state, currentOperand: payload.digit, }; } so that even though the currentOperand does not include a 0 at initial loading, when pressing "." it will populate 0.XX. It appears to work as I hope with that change, but I am still currently learning React so please advise me if my code could be improved or is incorrect. I hope I communicated my suggestion clearly. Thank you again.
@Fatima Faz what button? After the project is finished? Check if you have any errors in your console, it usually is the best way to find out where the problem is coming from
I just finished my React calculator. I came here to make a comparision, that's my favourite style of learning. Thanks, Buddy. I like your tutorials the most, they are indeed simplified.
Seems very knowledgeable on React, I think it would be benificial if he slowed down and explained the code as went, rather than repeat what he is writing down. After watching this video, I feel like I know how to make a React calculator, but I didn't learn much about React.
in defence of Kyle: as a senior citizen with no programming knowledge but programming enthusiastic I learned Node.js, MongoDb from Kyle's another video. IMO you'll experience this from shorter videos otherwise the video might get quite long if everything is explained in detail. What I had done with that tutorial was with every main concept I did a bit of further research to get my concepts right and learnt zillion things while doing that and would suggest everyone watching such tutorials. All in all, again in IMO Kyle is such a knowledgable person with great skill of explaining stuff.
Thank you for the free instruction. As others have commented the title is misleading. As this is not a beginner React Project. I did get value from it but true begineers like myself should not do this first but the javascript only version and reducer video first. Thank you I am grateful.
You have to remember that react is a package that builds on-top of a programming language. That means that while its totally correct to call it a beginner react project, you shouldnt treat this as something a beginner can easily digest without knowing the programming language it’s built on top of in the first place. Having worked with nodejs for years now and having taken part of much larger React projects, i fully agree this only touches on the basic contents of React.
The calculator evaluation part might be lil tricky for someone who is not that proficient in dsa programming but overall webdev and stuff was way too informative and clear. Grasped a lot of new things from the tutorial.
I love how at then end he says "And thats all it takes" like that was some simple thing lol. thank you for the tutorial.. this helped me understand useReducer a bit better
It does display the Infinity symbol, which could be considered correct. Then you could add a check in the CHOOSE_OPERATION case to not allow any subsequent operations with Infinity if (state.currentOperand == Number.POSITIVE_INFINITY) return {};
Hey Kyle, something I thought would be neat is to make an exception to the "change operation" rule to allow a minus sign to infer a negative number as opposed to changing the operation entirely. This could be done by modifying the delete button to also delete the operation symbol, thus having a backup option in the case that a minus operation was intended. Stacking minus signs to do a "Minus this negative number" would also be very useful. I'm sure this begins to approach the realm of scientific calculators, of course, just a thought I had.
Very nice video! Thank you very much! Some edge cases that were not covered: 1. you can still add a 0 and then any digit 2. if you start with a ".", the application crashes (currentOperand is undefined) if anyone was wondering how to fix these: fix for 1 = add following check: // If a number is entered and the current operand = 0 then overwrite. if (payload.digit && state.currentOperand === "0") { return { ...state, currentOperand: payload.digit } } fix for 2 = add ? operator to check for multiple periods: if (payload.digit === "." && state.currentOperand?.includes(".")) { return state; }
I am a new React developer and I am getting "currentOperand is undefined" within my reducer function. Any idea how I can fix this? It is my only error at the moment.
There should be a lot of quotes around the word beginner. However, a good way to make people learn reducers. I've been asked about them in several interviews.
I'm having an issue. When coding the reducer I'm getting an error saying ${currentOperand} isn't defined at this point. switch(type){ case ACTIONS.ADD_DIGIT: return { ...state, currentOperand: `${currentOperand || ""}${payload.digit}`, } } I understand why it's happening since currentOperand is being defined in the same line that uses the reducer. function App() { const [{currentOperand, previousOperand, operation}, dispatch] = useReducer(reducer, {}); } but I have no idea how you managed to bypass this issue when you were coding it, any feedback on this would be much appreciated.
I checked the video again and it turns out you added 'state.' in front of currentOperand but cut that part of the video out for some reason. EDIT: You also forgot to mention to add a default: case to the switch case statement so that the data appended in the display.
Hi Everyone I am getting the below error when using the currentOperand , previousOperand,operation as property it shows undefined undefined undefined undefined till 1000lines. it is giving that error const [{previousOperand,currentOperand,operation},dispatch] = useReducer(reducer,{}); {previousOperand} {operation} {currentOperand} Please help me out with these!
Awesome tutorial!!! This is much complicated than I thought but you explain it very well. Only one part that I couldn't understand and still unsolvable is that if I click on '.' before clicking anything else, I got the error page
I had same issue but found this in one of the earlier comments which fixed it: This can be fixed by using optional chaining on the currentOperand: if (payload.digit === "." && state.currentOperand?.includes(".")) {
Great Beginner Project Thank you And If anyone comes across this error : " operand.split is not a function or its return value is not iterable" just convert the operand to a string using the toString()......operand.toString().split(".").
Kyle be careful with the cuts! You magically added code without going over it and I totally missed it and had to search around and compare because it wasn't working.
If your output div isn't growing with your inputs, that's because the word-wrap and word-break attributes are just as important as using minmax. I made that mistake and was stuck for a while. You have to use all 3.
Thx so much! 18:25 I found that when init state and first click ".", an error occurs. state.currentOperand?.includes(".") seems to solve this edge case maybe.. Also, this calculator not support first operand to be negative value right?
I have been studying webdev for about two months now, and besides that I have studied python for a couple of months to build scrapers. And I have a couple of useful scrapers for my work. But, I feel so stupid hearing this is a beginner project, I can't come close to creating such logic on my own. I know what the syntax does, I understand the code, but to come up with the logic part on my own is just bloody confusing. maybe I am far too much in tutorial hell.
that would be the imposter syndrome! I'm trying to get back into web dev after a year out and feel behind. It's tough, and takes some time for things to click. Take a step away and then come back to it! You'll get it!
Same! People said this is very simple and beginner-friendly tutorial. But I can barely understand and have a hard time following this tutorial even though I have learn coding for 3 years!
If you have done some DSA, Math or competitive programming stuff then this is very beginner friendly. That's what i felt. I could even implement all of the operation before his explanation.
So far haven't developed anything too fancy with React TBH, vanilla JS still comes more naturally to me I guess That's probably why I've never really gotten my head around the useReducer hook, but now that I saw it in action, it suddenly clicked. Thanks Kyle, REALLY gave me one of those light-bulb moments 💡
Cool video. Some nitpicks: 1) Display should always leave a 0 after clearing last digit or AC. 2) It seems you allowed one leading 0 in numbers, which is no good.
Cheers for the stretch. I first tried using a placehodler in currentOperand div. However as it wasn't state related, the field was still blank on first load. Next, I set the evaluate action to be set currentOperand to 0. This however didn;t solve the problem of first loading. Finally, when the state is declared with the useReducer hook, I set the default value inline there: const [{ currentOperand="0", previousOperand, operation }, dispatch ] = useReducer( Reducer, {} ); And that had it working as intended. Not sure on your second point. Do you mean numbers like "0567"? If so, ints beginning with zeroes are prevented.
I'm a true beginner in React and found this informative and challenging. Does anyone know why Kyle didn't include overwrite as a variable when he initialized his state with useReducer? He included currentOperand, prevOperand, operation in this statement: const [{currentOperand, prevOperand, operation}, dispatch] = useReducer(reducer, {}). Then he went onto to reference state.overwrite in his first if check in the ACTIONS.ADD_DIGIT case in his reducer function. How can you do that if you never declared what overwrite means in the first place?
This is awesome content as usual! One small thing I noticed while testing this: When the calculator is first loaded or AC/All Clear, if you press the decimal(".") button first, an error occurs because the currentOperand is null This can be fixed by using optional chaining on the currentOperand: if (payload.digit === "." && state.currentOperand?.includes(".")) {
Found this error as well, thanks for giving a quick fix. With testing it out, it automatically puts a 0 in front of it. Is this caused by the INTEGER_FORMATTER or is it due to something else?
@@C2W That is exactly right! Kyle did a great job with this formatter. Specifically, this is the line that matters, where it formats the blank text in 'integer' to 0: return `${INTEGER_FORMATTER.format(integer)}.${decimal}`;
Nice tutorial. I enjoyed the walkthrough of the CSS styling. One thing I discovered when building my own calculator is that for scientific calculators, if you press the sequence “2 + 2 *” it will not evaluate to 4 and await a number to multiply because multiplication takes priority over addition. Instead, it will wait for the next operand to perform the multiplication on. (Try typing this sequence on the iPhone calculator) Because of this, I don’t think using a reducer is a good idea for a calculator engine. It won’t really scale to more complex operators, like parentheses for instance. Actually, I think this tutorial actually has a negative influence because it seems to suggest that a reducer would be an appropriate tool for this sort of thing, but forcing a reducer for this is not only overly complex but also insufficient (because you’d have to add additional state to manage order of operations, and at a certain point, using a reducer is kind of pointless - it doesn’t add any value)
On my calculator, which was built nothing like this in the end cause I built it before watching this, I had if statements that essentially removed the last character from my evaluation if the last character inputted was not a number or %. It did however leave the * in the current expression and did it behind the scenes. This was actually quite a pita to get to work correctly, especially when I added the delete button as well then had to the same thing in reverse. Esp cause I didn't have the convenience of state in react as well.
It's amazing how much different this is than the calculator I built. I used regular js for mine cause I wasn't in react yet but our code is 100% not even close. I also had % and storage for history as well though. Side note - I was told never use eval for any reason ever as it's a huge security issue. I was essentially forced to find another option to evaluate my math which made my code more complex. Was I misinformed?
Don’t use eval. A safer and more customizable approach for performing the arithmetic is using an object mapping between the operation type and a binary function. Something like this (used TypeScript here but it’s not necessary): /* Type specifying a function that takes two number arguments and returns a number */ type BinaryCalcOp = (arg1: number, arg2: number) => number; /* Type that indicates an object of string keys with values of type BinaryCalcOp */ type OperationMap = Record; const operationMap = { ‘+’: (a, b) => a + b, ‘x’: (a, b) => a * b, ‘/’: (a, b) => a / b, ‘%’: (a, b) => a % b, ‘^’: (a, b) => a ** b, } as const satisfies OperationMap; The nice thing about this is that you can now add something like ‘^’ to perform exponentiation. Using eval will treat ‘^’ like a bitwise AND which is not what you want, but because you are in control of the mapping, you dictate what it means. Now the main chunk of the evaluate function from the video would look like this which is much nicer imo: return operationMap[operation](prev, current)
at 28:36 I think the final eturn in DELETE_DIGIT should be return { ...state, currentOperand: state.currentOperand.slice( 0, state.currentOperand.length - 1 ), }; because slice(0,1) just cuts the current operand to 1 digit
This is a great tutorial and so helpful. Firstly, thanks for creating this video. Let me suggest the error that I found at the 18:10 part, if we do like this and when we start with (.) it happens the error and shows undefined value for reading includes. we can fix it like that (state.currentOperand?.includes(".")) by adding the optional operator (?). Great work and perfect.
From 14:38, in the reducer function in the case of add_digit, the return changed from currentOperand to state.CurrentOperand suddenlyin 15:04..... I spent HOURS TRYING TO FIGURE OUT WHAT'S WRONG CAUSE I WAS FOLLOWING STEP BY STEP AND THAT WASN'T INCLUDED IN THE STEPS IT WAS EDITED INTO THE VIDEO 😭😭😭😭😭😭😭😭😭.. HOURS MAN. Ehy has no one in the comment even mentioned it
so he didnt mention in the video because he cut the part where he edit the video and the code should be currentOperand: `${state.currentOperand || ""}${payload.digit}'
Well I thought it was to quite new people in React, but I tried to follow up and realize that it wasn't. It is necessary to have had already basic React knowledge.
Some improvements for accessibility: - use separate grids for numbers and operators : moving from one number to another with the keyboard will be less cumbersome to do. - Allow to type numbers and operators directly (when the text input is focused) instead of using the mouse or tab - trigger the "clicked" CSS animation when you type a number, operator or AC/Back in the input field - do not forget to tell the user about available keyboard shortcut with labels (they appear as a tooltip when you let the mouse on the associated item) - find a way to translate all instructions - use focus to let assistive technologies show or read aloud the result of the calculation when you trigger "=" or "AC" actions - find a way to translate labels to French, Greek, Arabic, Russian, Chinese... Be careful to shift to right to left UI when required ! - as an exercise, try to build a calculator with roman numbers ;-) Yeah you didn't imagine how a simple calculator could be such a pain to make accessible and compliant with most countries isn't it ? Think of it the next tome you are asked to tell how much time you need to build such a calculator from scratch ;-) P.S : now try to use for same mindset to build an international date picker : beware that sone countries doesn't use our Gregorian calendar, start their weeks on Sunday or Tuesday instead of Monday, and so on....
Hi Kyle, when after refreshing the application & when there's no *currentOperand* or *previousOperand* inputted in the Black screen looking part of the calculator, & when I click on *.* (Decimal operand) of the calculator, then it throws an Error stating : *Cannot read properties of undefined (reading 'includes')* *TypeError: Cannot read properties of undefined (reading 'includes') at reducer* There's no useCase for this situation implemented.. So for this at *action.type* : *ACTIONS.ADD_DIGIT* case, we can simply write down condition : *if (payload.digit === "." && state.currentOperand == null) {* *return state;* *}* just before the condition *if (payload.digit === "." && state.currentOperand.includes(".")) {* *return state;* *}*
Awesome explanation, but I don't think this is for beginners...there has to be more than basic knowledge to understand what you are doing. Other than that, thanks!
Every concept he used was beginner's stuff. But putting them together into a working application that achieves the desired functionality is much more difficult. That's why tackling stuff like this, even if you're still a beginner, is a great way to learn - even if you fail. Like anything in life: you learn from failure more than anything!
Thanks for the content, your work is amazing! The app will error if you type a decimal point (.) as the first digit. I solved it by adding a check if the state.currentOperand was not empty.
@@behradkayedi3195 On line 27 of App.js, I added this to the if statement: " && state.currentOperand". So the final if statement will look like this: if (payload.digit === "." && state.currentOperand && state.currentOperand.includes(".")) { return state }
I keep getting an error where it says "currentOperand is not defined" I have no idea how to fix this issue as I have done everything he has done. Any pointers would be greatly appreciated!
when writing html in VSC you can do element.className and it'll auto create element with the classname Ex. div.output would be div with classname output
Whenever I apply formatOperand to previous-operand and current-operand the way its shown in the video, I keep getting "assignment to constant variable".
Please could you slow down in future videos, this doesnt have to be a speed run. I have to pause the video every 10 seconds to catch up on the code. I really appreciate the content ad you explaining everything, Im learning a lot, but can you just speak a bit slower, so we can code as you go, instead of stop/starting every few seconds. Thanks
what if you press period '.' first? I'm getting error "...undefined reading 'includes' "- I put '?' before .includes- works fine- how would you resolve it?
the calcilator is perfect but when you click only "." then it will throw some error. Also when the anser is in fraction then it will shows large number after "." (point). there is no limit at all
i tried to follow this lesson step by step but every time vscode gives me the same problem... return { ...state, currentOperand: `${currentOperand || ""}${payload.digit}` } it always says that currentOperand is not defined i checked 3 times the lesson but no trace of mistakes. someone of you got the same problem?
This is not simple one.
It's pragmatic, cognitive and help to comprehend the fundamentals.
Thanks for the content.
Kudos to your efforts.
LITERALLY I WAS ABOUT TO DIE LAST 5 MINUTES I WAS LIKE DUDEEEEEEE ITS ENOUGHHH!! ITS CALCULATING SOME OPERANDS SO LET IT GOOO PLEASEEEEEEEE!!!!
all of the concepts he used here are beginner's stuff. But putting it all together into something that works is much more difficultt.
Love how this dude is in 1.5x by default. Great tutorial!
I watch all of youtube @ 1.5x +. I stuck this on to 1.25x and had to slow it to 1x LMFAO - Your comment cracked me up :)
@@nicksmith5306 i can only follow him at 0.75x XD
Yeah man, need to play him at 0.9x otherwise I cant. Simply cant.
yap, not possible to follow on 1x
i was thinking the same thing. "he talks fast compared to other videos."
I appreciate all the effort put in the video. Is it me or there was someone else that didn't really understand still? Ugh, I was just coding along with question marks in my head.
same, I could not understand from when the logical part started.
Just completed, thank you for the great tutorial. Wasn't a beginner project in my opinion due to the amount of complex logic implemented in this one. Glad I was able to follow along and complete this with you. I was expecting this to take me about 2 hours to finish but instead took me like 4-5 hours, just so that I could make sure I could understand everything that was going on.
This is NOT a beginner's React tutorial lol ... still a nice one. Helped me to understand useReducer and the pattern a bit more.
Thanks so much Kyle, this was an awesome project to start with.
Just two things I noticed, first as Ninjashot mentioned, there is a step missing in the tutorial and that is adding "state" in front of currentOperand when creating ADD.DIGIT case. This should look like this:
return {
...state,
currentOperand:`${state.currentOperand || ""}${payload.digit}`,
}
And another bug I noticed while playing with the calculator and testing it, is that the app would crash when pressing "." with no digits there.
This can be easily solved by adding the following line on top of the other If statement you have for the "." case on payload digit:
This should look like this:
if (payload.digit === "." && state.currentOperand == null) { return state }
if (payload.digit === "." && state.currentOperand.includes(".")) { return state }
Also I checked that all the calculators I have when pressing AC a "0" is displayed, so if you want to add that behaviour, just change the ACTIONS.CLEAR case to this:
case ACTIONS.CLEAR:
return {
...state,
currentOperand: "0",
previousOperand: null,
operation: null
}
It should work fine after that. I appreciate the hard work it took for you to share this with us :)
Thank you so much ahah, I was looking for why it was not working and you catched the mistake for me :)
i am not getting state.currentOperand == null works
state.currentOperand === null WON'T work WHY...?
@@mdmustaqahmed5391 Hi Mustaq, not sure of which part you’re talking about, but can you please comment what error is thrown? Usually it tells you which line of code is the one causing the issue, it could potentially be something else in your code
Thank you Marco, this was very helpful. May i suggest a change to your:
if (payload.digit === "." && state.currentOperand == null) { return state }
After refreshing the application, the currentOperand is null and if you press "." it does not immediately start a "0.XXXX" with your suggestion above, so I modified your suggestion to:
if (payload.digit === "." && state.currentOperand == null) {
return {
...state,
currentOperand: payload.digit,
};
}
so that even though the currentOperand does not include a 0 at initial loading, when pressing "." it will populate 0.XX.
It appears to work as I hope with that change, but I am still currently learning React so please advise me if my code could be improved or is incorrect.
I hope I communicated my suggestion clearly. Thank you again.
@Fatima Faz what button? After the project is finished? Check if you have any errors in your console, it usually is the best way to find out where the problem is coming from
I just finished my React calculator. I came here to make a comparision, that's my favourite style of learning. Thanks, Buddy. I like your tutorials the most, they are indeed simplified.
I can't even describe how much work this guy saved me with these videos.. What a legend
Seems very knowledgeable on React, I think it would be benificial if he slowed down and explained the code as went, rather than repeat what he is writing down. After watching this video, I feel like I know how to make a React calculator, but I didn't learn much about React.
in defence of Kyle: as a senior citizen with no programming knowledge but programming enthusiastic I learned Node.js, MongoDb from Kyle's another video. IMO you'll experience this from shorter videos otherwise the video might get quite long if everything is explained in detail. What I had done with that tutorial was with every main concept I did a bit of further research to get my concepts right and learnt zillion things while doing that and would suggest everyone watching such tutorials.
All in all, again in IMO Kyle is such a knowledgable person with great skill of explaining stuff.
agreed
Just slow down the video man, you can adjust the playback speed
Solid video! Apart from the usual too-fast-even-for-youtube-playback-adjustment, it was very helpful! Thanks man!
it was so fast man. couldn'tt keep up
Thank you for the free instruction. As others have commented the title is misleading. As this is not a beginner React Project. I did get value from it but true begineers like myself should not do this first but the javascript only version and reducer video first. Thank you I am grateful.
how dafaq is this beginner friendly
The final code/product can look daunting, but if you look at each component, hook, css class alone, they all using simple concepts.
Swear to god I was like, Okay I'm worse than a beginner I'm just null.
You have to remember that react is a package that builds on-top of a programming language. That means that while its totally correct to call it a beginner react project, you shouldnt treat this as something a beginner can easily digest without knowing the programming language it’s built on top of in the first place. Having worked with nodejs for years now and having taken part of much larger React projects, i fully agree this only touches on the basic contents of React.
The calculator evaluation part might be lil tricky for someone who is not that proficient in dsa programming but overall webdev and stuff was way too informative and clear.
Grasped a lot of new things from the tutorial.
Before you dive into React, you should already understand the basics of JS, CSS and HTML
The chance that I watched the original 2 year old video last night cause it was recommended.
Was it with React or vanilla JS?
I literally watched the original video last night, but unlike you it wasn’t recommended, I searched for it and the next day he made a newer version 😂
@@123ftw1 i think it was vanilla js
@@123ftw1 vanilla
SAME
Kyle breathes in React and he is so skillful at explaining with examples at a really intuitive and fast-iterative pace. Great job Kyle!
pretty much, Kyle looks like he is 26 or something yet has senior level knowledge of react...
About to follow along to this now, and to make it a little more challenging I'll do it in TypeScript
I'm rusty as hell. Started with JSX and will try TSX next! Good luck!
02:27 Btw we can write divide symbol by simply holding ALT + 0247 and release alt after that
I love how at then end he says "And thats all it takes" like that was some simple thing lol. thank you for the tutorial.. this helped me understand useReducer a bit better
that's so much easier than the vanilla javascript one, now i know it's worth it to learn react, great vid, thanks
Hi Kyle, Do you increase playback speed while Editing the video? it seems like you make it 1.25x, just asking
Too much of information and concept explained with ease.
Thanks a lot ❤️.
23:23
You forgot to put a statement to prevent user trying to divide by 0.
It does display the Infinity symbol, which could be considered correct. Then you could add a check in the CHOOSE_OPERATION case to not allow any subsequent operations with Infinity
if (state.currentOperand == Number.POSITIVE_INFINITY) return {};
Hey Kyle, something I thought would be neat is to make an exception to the "change operation" rule to allow a minus sign to infer a negative number as opposed to changing the operation entirely. This could be done by modifying the delete button to also delete the operation symbol, thus having a backup option in the case that a minus operation was intended. Stacking minus signs to do a "Minus this negative number" would also be very useful. I'm sure this begins to approach the realm of scientific calculators, of course, just a thought I had.
i just love your style of using useReducer, u just made a nice usecase for hook
Very nice video! Thank you very much!
Some edge cases that were not covered:
1. you can still add a 0 and then any digit
2. if you start with a ".", the application crashes (currentOperand is undefined)
if anyone was wondering how to fix these:
fix for 1 = add following check:
// If a number is entered and the current operand = 0 then overwrite.
if (payload.digit && state.currentOperand === "0") {
return {
...state,
currentOperand: payload.digit
}
}
fix for 2 = add ? operator to check for multiple periods:
if (payload.digit === "." && state.currentOperand?.includes(".")) {
return state;
}
I am a new React developer and I am getting "currentOperand is undefined" within my reducer function. Any idea how I can fix this? It is my only error at the moment.
have to say this was my first complete slightly complex react project and i enjoyed it thanks kyle
Great calculator, thanks!!
I would love to see more tutorial videos from you
Kyle is on highspeed here. Must be a pizza in the oven.
Very good introduction to react. Love it.
It's hard to program but it's even harder to teach programming, yet you make it so simple! Fucking love this channel
There should be a lot of quotes around the word beginner. However, a good way to make people learn reducers. I've been asked about them in several interviews.
While watching your video, I follow your instructions and implemented same calculator.
Thanks Buddy!!!
I'm having an issue. When coding the reducer I'm getting an error saying ${currentOperand} isn't defined at this point.
switch(type){
case ACTIONS.ADD_DIGIT:
return {
...state,
currentOperand: `${currentOperand || ""}${payload.digit}`,
}
}
I understand why it's happening since currentOperand is being defined in the same line that uses the reducer.
function App() {
const [{currentOperand, previousOperand, operation}, dispatch] = useReducer(reducer, {});
}
but I have no idea how you managed to bypass this issue when you were coding it, any feedback on this would be much appreciated.
I checked the video again and it turns out you added 'state.' in front of currentOperand but cut that part of the video out for some reason.
EDIT: You also forgot to mention to add a default: case to the switch case statement so that the data appended in the display.
@@ninjashot37 Thank you very much.... it took me so long to figure out what i was doing wrong... and this comment guided me there.
@Lautaro Clerici Erhardt
case ACTIONS.ADD_DIGIT:
return {
...state, currentOperand: `${state.currentOperand || ''}${payload.digit}`
}
Hi Everyone I am getting the below error when using the currentOperand , previousOperand,operation as property it shows undefined undefined undefined undefined till 1000lines. it is giving that error
const [{previousOperand,currentOperand,operation},dispatch] = useReducer(reducer,{});
{previousOperand} {operation}
{currentOperand}
Please help me out with these!
@@rickeyupadhyay6898 @ 15:04 he deletes the line "dispatch({ type: ACTIONS.ADD_DIGIT, payload: { digit: 1}})"
Awesome tutorial!!! This is much complicated than I thought but you explain it very well. Only one part that I couldn't understand and still unsolvable is that if I click on '.' before clicking anything else, I got the error page
I had same issue but found this in one of the earlier comments which fixed it:
This can be fixed by using optional chaining on the currentOperand:
if (payload.digit === "." && state.currentOperand?.includes(".")) {
@@jeffreyclaybrook Thank you. I only missed the '?' .....
Great Beginner Project Thank you
And If anyone comes across this error : " operand.split is not a function or its return value is not iterable" just convert the operand to a string using the toString()......operand.toString().split(".").
Thank you for this, it was actually pretty challenging using these concepts! Cheers!
Kyle be careful with the cuts! You magically added code without going over it and I totally missed it and had to search around and compare because it wasn't working.
What are you talking about?
@@eduardostamm7416 at 15:03, he edited state.currentOperand instead of currentOperand in the switch case, took me a while to figure it out
Love the way you cover each and every test case, thank you
A great beginner's project, I learned a lot from it, especially about reducer hooks. thankyou.
you're great at explaining things, this video has certainly improved how i comprehend react.
If your output div isn't growing with your inputs, that's because the word-wrap and word-break attributes are just as important as using minmax. I made that mistake and was stuck for a while.
You have to use all 3.
You are so awesome! Right now I need this calc app for one of my input fields... great timing and wonderful tutorial! Thanks a lot! :)
Hi Kyle, as usual awesome video. You know what would be an awesome follow-up: doing a Svelte version of this video
this is nowhere near beginner, but thanks for the video i learned a lot, even though i gave up typing with you after you went crazy with functions
Thx so much!
18:25 I found that when init state and first click ".", an error occurs.
state.currentOperand?.includes(".") seems to solve this edge case maybe..
Also, this calculator not support first operand to be negative value right?
this project helped me end my doubt on react. but please next time dont be so quick
I recommend creating buttons from 1-9 with a function and pass the value as props
Dear Kyle how can you be so fast ? Truely you breathe in React ! Kudos to your knowledge..
I have been studying webdev for about two months now, and besides that I have studied python for a couple of months to build scrapers. And I have a couple of useful scrapers for my work.
But, I feel so stupid hearing this is a beginner project, I can't come close to creating such logic on my own. I know what the syntax does, I understand the code, but to come up with the logic part on my own is just bloody confusing. maybe I am far too much in tutorial hell.
that would be the imposter syndrome!
I'm trying to get back into web dev after a year out and feel behind. It's tough, and takes some time for things to click. Take a step away and then come back to it!
You'll get it!
Same! People said this is very simple and beginner-friendly tutorial. But I can barely understand and have a hard time following this tutorial even though I have learn coding for 3 years!
If you have done some DSA, Math or competitive programming stuff then this is very beginner friendly. That's what i felt. I could even implement all of the operation before his explanation.
So far haven't developed anything too fancy with React TBH, vanilla JS still comes more naturally to me I guess
That's probably why I've never really gotten my head around the useReducer hook, but now that I saw it in action, it suddenly clicked.
Thanks Kyle, REALLY gave me one of those light-bulb moments 💡
Im not a react developer but the word reducer and dispatch says nothing to me, I would call it something else.
@@hombacomthe choice of names for some things in react are not very intuitive. Useffect is another one
Glad I found you. Great instructor!
I haven't watched this but I already know I am gonna love it.
Cool video. Some nitpicks:
1) Display should always leave a 0 after clearing last digit or AC.
2) It seems you allowed one leading 0 in numbers, which is no good.
Cheers for the stretch.
I first tried using a placehodler in currentOperand div. However as it wasn't state related, the field was still blank on first load.
Next, I set the evaluate action to be set currentOperand to 0. This however didn;t solve the problem of first loading.
Finally, when the state is declared with the useReducer hook, I set the default value inline there:
const [{ currentOperand="0", previousOperand, operation }, dispatch ] = useReducer( Reducer, {} );
And that had it working as intended.
Not sure on your second point. Do you mean numbers like "0567"? If so, ints beginning with zeroes are prevented.
2)
if (payload.digit && state.currentOperand === "0") {
return {
...state,
currentOperand: payload.digit,
}
}
I'm having this error "currentOperand' is not defined "
I am also having this error around 15 minute mark of video!
@@Michael-gp1mu I would recommend to not to follow this tutorial. I successfuly made a reactjs calculator from other method.
mine worked once I added a default case to the switch statements, I really enjoyed this tutorial and learning about the useReducer hook :)
I'm a true beginner in React and found this informative and challenging. Does anyone know why Kyle didn't include overwrite as a variable when he initialized his state with useReducer? He included currentOperand, prevOperand, operation in this statement: const [{currentOperand, prevOperand, operation}, dispatch] = useReducer(reducer, {}). Then he went onto to reference state.overwrite in his first if check in the ACTIONS.ADD_DIGIT case in his reducer function. How can you do that if you never declared what overwrite means in the first place?
Video just at the right time, when I was searching for the calculator project in React❤️❤️
this guy is such a boss at css
This is awesome content as usual! One small thing I noticed while testing this: When the calculator is first loaded or AC/All Clear, if you press the decimal(".") button first, an error occurs because the currentOperand is null
This can be fixed by using optional chaining on the currentOperand:
if (payload.digit === "." && state.currentOperand?.includes(".")) {
Good find. I replaced it instead with a check that will set the currentOperand to "0." instead. So users can type ".25" and it outputs to "0.25".
Found this error as well, thanks for giving a quick fix.
With testing it out, it automatically puts a 0 in front of it. Is this caused by the INTEGER_FORMATTER or is it due to something else?
@@C2W That is exactly right! Kyle did a great job with this formatter. Specifically, this is the line that matters, where it formats the blank text in 'integer' to 0:
return `${INTEGER_FORMATTER.format(integer)}.${decimal}`;
@Jesse Parent, whats would be the return statement be though? tried multiple ways but the application still crashes :/
This is a very good beginner project for someone with mid level experience. The title is a bit off.
This is anything but SIMPLIFIED!!
I watched many of his videos and I can surely say none of his videos make web dev simpler by any means.
Nice tutorial. I enjoyed the walkthrough of the CSS styling.
One thing I discovered when building my own calculator is that for scientific calculators, if you press the sequence
“2 + 2 *” it will not evaluate to 4 and await a number to multiply because multiplication takes priority over addition. Instead, it will wait for the next operand to perform the multiplication on. (Try typing this sequence on the iPhone calculator)
Because of this, I don’t think using a reducer is a good idea for a calculator engine. It won’t really scale to more complex operators, like parentheses for instance.
Actually, I think this tutorial actually has a negative influence because it seems to suggest that a reducer would be an appropriate tool for this sort of thing, but forcing a reducer for this is not only overly complex but also insufficient (because you’d have to add additional state to manage order of operations, and at a certain point, using a reducer is kind of pointless - it doesn’t add any value)
On my calculator, which was built nothing like this in the end cause I built it before watching this, I had if statements that essentially removed the last character from my evaluation if the last character inputted was not a number or %. It did however leave the * in the current expression and did it behind the scenes. This was actually quite a pita to get to work correctly, especially when I added the delete button as well then had to the same thing in reverse. Esp cause I didn't have the convenience of state in react as well.
It's amazing how much different this is than the calculator I built. I used regular js for mine cause I wasn't in react yet but our code is 100% not even close. I also had % and storage for history as well though.
Side note -
I was told never use eval for any reason ever as it's a huge security issue.
I was essentially forced to find another option to evaluate my math which made my code more complex. Was I misinformed?
Yes you should never use eval , you can create calculator in 2 minutes using eval
Don’t use eval. A safer and more customizable approach for performing the arithmetic is using an object mapping between the operation type and a binary function. Something like this (used TypeScript here but it’s not necessary):
/* Type specifying a function that takes two number arguments and returns a number */
type BinaryCalcOp = (arg1: number, arg2: number) => number;
/* Type that indicates an object of string keys with values of type BinaryCalcOp */
type OperationMap = Record;
const operationMap = {
‘+’: (a, b) => a + b,
‘x’: (a, b) => a * b,
‘/’: (a, b) => a / b,
‘%’: (a, b) => a % b,
‘^’: (a, b) => a ** b,
} as const satisfies OperationMap;
The nice thing about this is that you can now add something like ‘^’ to perform exponentiation. Using eval will treat ‘^’ like a bitwise AND which is not what you want, but because you are in control of the mapping, you dictate what it means.
Now the main chunk of the evaluate function from the video would look like this which is much nicer imo:
return operationMap[operation](prev, current)
at 28:36
I think the final eturn in DELETE_DIGIT should be
return {
...state,
currentOperand: state.currentOperand.slice(
0,
state.currentOperand.length - 1
),
};
because slice(0,1) just cuts the current operand to 1 digit
Thankyou! I learnt a lot in 30 minutes.
This is a great tutorial and so helpful. Firstly, thanks for creating this video. Let me suggest the error that I found at the 18:10 part, if we do like this and when we start with (.) it happens the error and shows undefined value for reading includes. we can fix it like that (state.currentOperand?.includes(".")) by adding the optional operator (?). Great work and perfect.
Thanks a lot . It did help when i got stuck..
watching your videos on 0.75x and it seems perfect for me.
From 14:38, in the reducer function in the case of add_digit, the return changed from currentOperand to state.CurrentOperand suddenlyin 15:04.....
I spent HOURS TRYING TO FIGURE OUT WHAT'S WRONG CAUSE I WAS FOLLOWING STEP BY STEP AND THAT WASN'T INCLUDED IN THE STEPS IT WAS EDITED INTO THE VIDEO 😭😭😭😭😭😭😭😭😭.. HOURS MAN. Ehy has no one in the comment even mentioned it
i have a problem
src\App.js
Line 21:28: 'currentOperand' is not defined no-undef
so he didnt mention in the video because he cut the part where he edit the video and the code should be currentOperand: `${state.currentOperand || ""}${payload.digit}'
need to add state in front
It does work except the grid alignment of "calculator-grid"
bro this was supposed to be a beginner project... Now I am afraid of React thanks to you
"It looks simple" always made me realize the opposite!
Well I thought it was to quite new people in React, but I tried to follow up and realize that it wasn't. It is necessary to have had already basic React knowledge.
Some improvements for accessibility:
- use separate grids for numbers and operators : moving from one number to another with the keyboard will be less cumbersome to do.
- Allow to type numbers and operators directly (when the text input is focused) instead of using the mouse or tab
- trigger the "clicked" CSS animation when you type a number, operator or AC/Back in the input field
- do not forget to tell the user about available keyboard shortcut with labels (they appear as a tooltip when you let the mouse on the associated item)
- find a way to translate all instructions
- use focus to let assistive technologies show or read aloud the result of the calculation when you trigger "=" or "AC" actions
- find a way to translate labels to French, Greek, Arabic, Russian, Chinese... Be careful to shift to right to left UI when required !
- as an exercise, try to build a calculator with roman numbers ;-)
Yeah you didn't imagine how a simple calculator could be such a pain to make accessible and compliant with most countries isn't it ? Think of it the next tome you are asked to tell how much time you need to build such a calculator from scratch ;-)
P.S : now try to use for same mindset to build an international date picker : beware that sone countries doesn't use our Gregorian calendar, start their weeks on Sunday or Tuesday instead of Monday, and so on....
Hi Kyle, when after refreshing the application & when there's no *currentOperand* or *previousOperand* inputted in the Black screen looking part of the calculator, & when I click on *.* (Decimal operand) of the calculator, then it throws an Error stating :
*Cannot read properties of undefined (reading 'includes')*
*TypeError: Cannot read properties of undefined (reading 'includes') at reducer*
There's no useCase for this situation implemented..
So for this at *action.type* : *ACTIONS.ADD_DIGIT* case, we can simply write down condition :
*if (payload.digit === "." && state.currentOperand == null) {*
*return state;*
*}*
just before the condition
*if (payload.digit === "." && state.currentOperand.includes(".")) {*
*return state;*
*}*
How can you be so smart and good looking at the same time? 😂
Thanks a ton for the tutorial, appreciate it💯
Why at 19:53 , Kyle used "==" instead of "===", I used "===" and the logic discussed at 20:40 isn't working, if Kyle u r reading this, please clarify
WATCH THIS IN 0.75X SPEED IF YOU ARE A BEGINNER!!!
Awesome explanation, but I don't think this is for beginners...there has to be more than basic knowledge to understand what you are doing. Other than that, thanks!
Every concept he used was beginner's stuff. But putting them together into a working application that achieves the desired functionality is much more difficult. That's why tackling stuff like this, even if you're still a beginner, is a great way to learn - even if you fail. Like anything in life: you learn from failure more than anything!
great video dawg
kyle you a legend for this
20:30
can currentOperand be equal to an empty string instead of null? why or why not?
Thanx for this beautiful class. You are so awesome!
Thanks for the content, your work is amazing!
The app will error if you type a decimal point (.) as the first digit. I solved it by adding a check if the state.currentOperand was not empty.
Some elaboration would be great, as I'm struggling to implement this.
@@behradkayedi3195 On line 27 of App.js, I added this to the if statement: " && state.currentOperand".
So the final if statement will look like this:
if (payload.digit === "." && state.currentOperand && state.currentOperand.includes(".")) {
return state
}
@@edbean You're a real one for that, thanks
Did you handle the precision issue? What will be the output of 0.1*0.2
Is it 0.02 or 0.02000000000004?
Only you explain react.js this easy. Thanks 👍
I keep getting an error where it says "currentOperand is not defined" I have no idea how to fix this issue as I have done everything he has done. Any pointers would be greatly appreciated!
You have to change line of code in reducer function like that: currentOperand: `${state.currentOperand || ""}${payload.digit}` , so error won't appear
This is different man for a beginner
when writing html in VSC you can do element.className and it'll auto create element with the classname Ex. div.output would be div with classname output
Where is the entry for video intro like in VanillaJS calculator ? That chair roll and straight look is so cool!
Would it make more sense in the reducer function to destructure the state parameter? Or would that just make it confusing ?
Thanks a lot for this video, make me understand much more about react and useReducer
Whenever I apply formatOperand to previous-operand and current-operand the way its shown in the video, I keep getting "assignment to constant variable".
nvm I forgot to put '==' instead of '='
Please could you slow down in future videos, this doesnt have to be a speed run. I have to pause the video every 10 seconds to catch up on the code.
I really appreciate the content ad you explaining everything, Im learning a lot, but can you just speak a bit slower, so we can code as you go, instead of stop/starting every few seconds.
Thanks
Same case with me.
period button cause an error when nothing is being typed and there is no current or prev operator is exist in the state what do we do ?
Wich is better? the Hook useReducer or Redux?
amazing project specially if you want to make strong command on useReducer
what if you press period '.' first? I'm getting error "...undefined reading 'includes' "- I put '?' before .includes- works fine- how would you resolve it?
yes, me too
the calcilator is perfect but when you click only "." then it will throw some error. Also when the anser is in fraction then it will shows large number after "." (point). there is no limit at all
i tried to follow this lesson step by step but every time vscode gives me the same problem...
return {
...state,
currentOperand: `${currentOperand || ""}${payload.digit}`
}
it always says that currentOperand is not defined i checked 3 times the lesson but no trace of mistakes. someone of you got the same problem?
It gets changed to ${state.currentOperand || ""} in the 15:00 transition
@@virtohardiman Magic
Awesome project 👍
When I first saw your video, I said please speak slowly, but now I have to improve my English.