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.
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.
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.
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
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.
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
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.
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.
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(".").
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(".")) {
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.
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 💡
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'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?
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!
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.
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.
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
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.
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}`;
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
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}'
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
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)
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;* *}*
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.
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.
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....
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.
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 }
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
@Harry Pannu. I didn't manage to finish it to be perfect because of time constraint but went really well. I work for the company now as Full Stack Developer :)
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. too fast speed
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.
@Web Dev Simplified please help if(payload.digit==="0" && state.currentoperand==="0") return state this part is not working it keeps on adding zero over and over
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!
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."
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.
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.
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.
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.
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 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
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
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!
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.
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...
that's so much easier than the vanilla javascript one, now i know it's worth it to learn react, great vid, thanks
02:27 Btw we can write divide symbol by simply holding ALT + 0247 and release alt after that
Too much of information and concept explained with ease.
Thanks a lot ❤️.
While watching your video, I follow your instructions and implemented same calculator.
Thanks Buddy!!!
have to say this was my first complete slightly complex react project and i enjoyed it thanks kyle
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.
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
i just love your style of using useReducer, u just made a nice usecase for hook
A great beginner's project, I learned a lot from it, especially about reducer hooks. thankyou.
Thank you for this, it was actually pretty challenging using these concepts! Cheers!
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(".").
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 '?' .....
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
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 {};
you're great at explaining things, this video has certainly improved how i comprehend react.
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! :)
mine worked once I added a default case to the switch statements, I really enjoyed this tutorial and learning about the useReducer hook :)
Love the way you cover each and every test case, thank you
Dear Kyle how can you be so fast ? Truely you breathe in React ! Kudos to your knowledge..
Great calculator, thanks!!
I would love to see more tutorial videos from you
Hi Kyle, Do you increase playback speed while Editing the video? it seems like you make it 1.25x, just asking
I recommend creating buttons from 1-9 with a function and pass the value as props
It's hard to program but it's even harder to teach programming, yet you make it so simple! Fucking love this channel
this guy is such a boss at css
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.
Glad I found you. Great instructor!
watching your videos on 0.75x and it seems perfect for me.
Hi Kyle, as usual awesome video. You know what would be an awesome follow-up: doing a Svelte version of this video
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
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?
Video just at the right time, when I was searching for the calculator project in React❤️❤️
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.
Kyle is on highspeed here. Must be a pizza in the oven.
Very good introduction to react. Love it.
Thankyou! I learnt a lot in 30 minutes.
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 project helped me end my doubt on react. but please next time dont be so quick
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}})"
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.
I haven't watched this but I already know I am gonna love it.
kyle you a legend for this
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
amazing project specially if you want to make strong command on useReducer
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
Only you explain react.js this easy. Thanks 👍
This is a very good beginner project for someone with mid level experience. The title is a bit off.
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.
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 :/
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
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
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
Thanx for this beautiful class. You are so awesome!
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)
Thanks a lot for this video, make me understand much more about react and useReducer
This is different man for a beginner
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;*
*}*
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.
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 ?
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,
}
}
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....
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.
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.
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
Thank you for the tutorial, very helpful
Where is the entry for video intro like in VanillaJS calculator ? That chair roll and straight look is so cool!
It does work except the grid alignment of "calculator-grid"
20:30
can currentOperand be equal to an empty string instead of null? why or why not?
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
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
does anyone explain the overwrite , how does it work ?
Had to implement one of these using Angular while being interviewed for the company :P
@Harry Pannu. I didn't manage to finish it to be perfect because of time constraint but went really well. I work for the company now as Full Stack Developer :)
@Harry Pannu. thank you very much :D
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. too fast speed
Awesome project 👍
Thanks for this awesome guide
Thank you very much. I did it with react typescript.
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..
@Web Dev Simplified please help if(payload.digit==="0" && state.currentoperand==="0") return state this part is not working it keeps on adding zero over and over
You can get this character (÷) on mac by holding "option" and pressing "/"
PLS HELP
When I click on any operation, the dispatch runs CLEAR for some reason?? I'm at 21:00
Thank you! I am one step further.
Would it make more sense in the reducer function to destructure the state parameter? Or would that just make it confusing ?
"It looks simple" always made me realize the opposite!
When I first saw your video, I said please speak slowly, but now I have to improve my English.
Did you handle the precision issue? What will be the output of 0.1*0.2
Is it 0.02 or 0.02000000000004?
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