#still need to refactor it and make it /fancy/
Explore tagged Tumblr posts
Text
Also I'm just đ thrilleddd that some code I've been building in work for the past 3 weeks is fully functional now!!!
What a huge relief! Woo!
#ooc#still need to refactor it and make it /fancy/#i.e. take out all my api debugging lmao#but i am... okay... until next week's review đ„Č#hopefully my work doesn't get torn to pieces đ„ș#i really like what I've built <3#a kind of service thing where you can come along and integrate /any/ api you like#into some software that we're gonna try sell as a product next year#so it's cool nerdy stuff to me jfjgkjg#but ahhhh man i can finally reeelaxxxxx now <3
9 notes
·
View notes
Text
A New Light
At the start of 2019, we helped Roll20 Get a New Look with an update to Advanced Fog of War. While our data showed that the changes made the system run faster for many users, it also highlighted structural problems with the original design and architecture of that feature.
It became clear that we couldnât bandage up this feature. We needed to rebuild it from the ground up, leveraging modern tools and designing with an eye towards our users' needs. Thus began work on the project we called âA New Light.â
Today weâre ready to unveil the results. Meet Updated Dynamic Lighting, a completely refurbished Plus and Pro subscriber feature which integrates all the functions from our existing lighting system with one streamlined name and future-ready code. It runs faster, supports more use cases, and represents the single biggest Roll20 upgrade since⊠well, the original Dynamic Lighting.
The old system (Legacy Dynamic Lighting) will run alongside the new system (Updated Dynamic Lighting) at first, to give you time to adjust, and then the old system will be retired later in 2020. Weâll give you lots of advance notice when its retirement party is coming, but for now, just know that you can switch between systems when youâre ready to try out the new update.
Because of its size and importance, we have a lot to say about Updated Dynamic Lighting. We front-loaded the features list for those of you who want to get right to the point, but read beyond that for a more robust explanation of what changes we made and why.
Overall Features:
Performance boost
Plus and Pro subscriber only
More robust technology that will work with modern hardware and browsers more efficiently
Change in tech will let us deliver more, highly requested features
New Lighting Features:
Light radius and Vision radius are now two separate settings
Dim Light and Bright Light are individual settings
All Light can be seen by all players' tokens with Vision
Tokens can now have âNight Visionâ that doesnât require light
Explorer Mode Features:
Replaces âAdvanced Fog of Warâ with a toggle
Reveals in a radius around a token (no more grids!)
Saves revealed areas that a user has seen for all tokens they control
Visit the Roll20 Forum Bug Thread for more details and known issues about Updated Dynamic Lighting! Weâd love to hear your feedback.
Parallel Systems: Legacy and Updated Dynamic Lighting
Currently, 51% of Roll20 games use some form of Legacy Dynamic Lighting or Advanced Fog of War. With a feature that touches so many of your lives, the last thing we wanted to do was make a sudden switch on you. Therefore, weâre introducing Updated Dynamic Lighting feature as an opt-in feature that will eventually (but not for some time yet) replace Legacy Dynamic Lighting. These systems will remain active side-by-side until we feel confident that weâve met your expectations and given you enough time to switch.
Please be aware: Legacy Dynamic Lighting WILL be going away, but not until later in 2020. Given its structural problems, it would be untenable for us to support both versions of this system going forward. So we encourage you to try out the Updated Dynamic Lighting as soon as you can! Weâll make sure to give you a reminder well before the final change takes place.
Weâre also confident that youâll like it. The new system leverages WebGL, the same system that Legacy Dynamic Lighting always used. Whatâs new here is that the feature set from Advanced Fog of War has been integrated into the same system, and rebranded as âExplorer Mode,â a new setting for Updated Dynamic Lighting. In essence, this means that if you can run Legacy Dynamic Lighting, then you can run Updated Dynamic Lighting with the benefit of new features and substantially faster processing time.
We chose WebGL because it leverages the power of your computerâs graphics processor instead of taxing your CPU. We measured, and 99.9% of Roll20 users already use WebGL, and if youâre not sure whether that includes you, you can check with this webpage.
As with all Roll20 features, Dynamic Lighting has been designed for use on our officially supported browsers, Firefox and Chrome. You will need to use one of these browsers for the features to perform correctly.
What Happens When You Switch?
If you already have Dynamic Lighting barriers drawn on your Dynamic Lighting layer, those will stay. The new system uses that same layer to create line of sight for your map. However, if you were using Advanced Fog of War to remember where your players have already explored, their memory of revealed portions of the map will not carry over to Updated Dynamic Lighting. For that reason, itâs best to make the switch when moving your players to a new Page.
But donât worry: if you want to switch back, you can. In essence, both Updated and Legacy Dynamic Lighting have separate memories of where your players have been, so whatâs revealed in one system will not be revealed in the other. When you switch back and forth between them, however, they will each retain their individual memory of areas revealed while that system was active in your game.
As mentioned above, the feature set from the old âAdvanced Fog of Warâ system has been integrated and renamed âExplorer Modeâ for Updated Dynamic Lighting. It functions in the same way: as your players move their tokens around the play area, those sections of the map will be revealed and remembered. You just need to toggle Explorer Mode on.
Several other features have been rebranded for Updated Dynamic Lighting. You can read more about them on the Roll20 Help Center. Lots of newer GMs told us they had trouble understanding how the different pieces of the lighting system interacted with each other. We hope that the new names help shine light (!) on those issues, but hey! Let us know your feedback on the forums.
How to Turn on Updated Dynamic Lighting
Updated Dynamic Lighting will exist alongside the old systems for now, but you canât use them both at the same time. When you enable Updated Dynamic Lighting, the old system will be disabled - but donât worry! It only applies to the page you change the setting for, and you can revert if you wish. Make sure you read the âWhat Happens When You Switch?â section above for more detail on changing systems!
How to enable Updated Dynamic Lighting on a map or page:
In the Page Menu, click on the Gear Icon for the Page you want to edit.
Find the section in Page Settings labeled Updated Dynamic Lighting and switch it on.
Optional: If you want your players to retain visibility of the Map Layer after they have left their vision radius, turn on Explorer Mode (replaces âAdvanced Fog of Warâ)
Optional: If you want to avoid placing lights, or itâs an outside, sunny kind of adventure, turn on Daylight Mode (replaces âGlobal Illuminationâ)
Click Save on the Page Settings
How to give an object Vision on an Updated Dynamic Lighting page:
Select the object (such as a character token or a pet controlled by a player)
Make sure that itâs Controlled By the correct players
Navigate to the âUpdated Dynamic Lightingâ tab
Turn on Vision
Optional: Turn on Low Light Vision radius
Optional: Turn on Night Vision radius
How to Light up an object on an Updated Dynamic Lighting page:
Select the object (such as a torch or character with a flashlight duct-taped to their head)
Navigate to the âUpdated Dynamic Lightingâ tab
Set the Bright Light radius to the distance that bright light should be emitted
Optional: Set the Low Light radius (usually larger than Bright Light)
Optional: Set the Angle and Starting Degree of light emitted (for a flashlight, etc)
Voila! Or âque la lumiĂšre soit,â if you want to get fancy. As long as you have Dynamic Lighting barriers set up (and you can learn how to do that on this Roll20 Help Center article), your page is ready. You can also check your work by selecting a token and hitting Ctrl + L to see what that token would see.
Support for Roll20 Marketplace Products
When you switch over to Updated Dynamic Lighting for your existing products from the Roll20 Marketplace, you may notice that some areas of your lighted maps have light leaking through corners and around walls. We'll be fixing this for all products (including Marketplace Creator products) with future patches to Updated Dynamic Lighting, so please donât worry that you will need to correct this by hand for all your maps!
Whatâs happening here: Updated Dynamic Lighting is far more precise about detecting the exact length and placement of barriers on the Dynamic Lighting layer. In places where the lines of a corner donât join up 100% precisely, light will now shine through that small gap. Sometimes, Updated Dynamic Lighting, you do your job too well. Weâre scoping out some tweaks to close those gaps moving forward!
You can still start or continue playing on existing maps during this time, but we recommend checking for light leaks before you let your players loose on them. The last thing any GM wants to hear is âUh, I think I can see the boss through this corner?â Keep your secrets hidden, and weâll keep you posted on the patches that will correct this problem in the future.
The Future of Dynamic Lighting
So whatâs new in Updated Dynamic Lighting? Everything! And nothing. Under the hood, the code has been entirely refactored. Although the whole system is smoother and more efficient, we designed it to parallel the existing feature set of Legacy Dynamic Lighting. Explorer Mode (previously Advanced Fog of War) has gotten huge performance upgrades that are really cool if youâre the type of person who gets excited about the fact that it now renders revealed areas in a circle instead of a square. (FYI, weâre the type of people who get excited about circles instead of squares. CIRCLES, everyone! Round happy circles!)
Even if you donât care about circles, the new system opens up a whole range of possibilities for the future. With A New Light complete, we can add more graphics features: specifically, the Layer Up update that was delayed last year and remains the most popular user request of all time. We also have a ton of exciting user ideas on the Suggestions Forum for lighting improvements that are much more doable with the added power of WebGL.
We also did some tinkering under the hood to add new features. One of the requests that drove us to embrace the need for a new system was our users' desire to have lighted objects be visible outside a characterâs immediate vision radius - like the glow of a faraway campfire, beckoning you through the dark. The old system made this possible through some twists and contortions, but Updated Dynamic Lighting allows any object with Vision to detect any object with Light. Simple as that.
This is just the beginning, and weâre excited to shine A New Light on Roll20âs future. Please give our new Updated Dynamic Lighting a try, and let us know what you think on the forum!
26 notes
·
View notes
Note
18 please!
Do any of your stories have alternative versions? (plotlines that you abandoned, AUs of your own work, different characterisations?) Tell us about them.
Yes! So I will use my WIP Done with Love
ORIGINS
ORIGINALLY THIS STORY WAS NOT SUPPOSED TO HAVE ShikaSaku.Â
IT WAS SUPPOSED TO BE ONLY ITASAKU. LOOK HOW FAR WE HAVE FALLEN BECAUSE I FELL HARD FOR SHIKA.
Literally never considered the pairing until this.Â
This story started with the Itasaku oneshot that is the prologue. Then I wrote a drabble that was just the hospital scene, but a little different. It had Kurenais daughter coming in wounded. Sakura saves her and goes to the waitingroom to find Shika a mess. It's the end of her shift so she takes him out for a drink. The end.
Then I decided, no I want to write a proper story. So I combined them, with Shikamaru only there because of his big brain AND THATS IT. NOTHING ELSE. So I added...They talk. Shika owes her one bigtime. Asuma would have haunted him forever if she died. So, Sakura says - I know how you are going to help me out. Help me train and I am going to get Sasuke back all on my own. Work with me on a strategy. The start of the chapter was a flash forward to an event I can tell because its a spoiler! Basically, Sakura is captured and trying to escape. This helped add some suspense to the exposition and make a boring capture time more interesting by breaking it up.Â
BUT then I decided to redo it completely. Because I fell in love with shikasaku as a later pairing.Â
Also - all those Kakashi moments - ACCIDENTAL. I wrote that healing scene in the library on a whim and now here we are. Originally, just supposed to be Shika and Itachi.
DELETED/REFACTORED SCENE
One additional diversion was the scene in the art gallery. That originally didnât have the genjutsu at all. It was an argument outside in a part. But I wanted to make it relevant to her training, so I put it in the gallery. In the alternate scene, it started because Sakura confronted Shikamaru about how he had kissed Ino before and wanted to know what kind of kiss it was. Here it is in DRAFT FORM:
âOh, Sai!â Inoâs voice shatters through the moment. Ino bounds up behind Sai, throwing her arms around him in greeting.
âSo this is where youâve been hiding from me.â She says sweetly.
âBeautiful, I was not hiding, I assure you.â He says, face looking phonier than before. Why did Ino get a nice nickname, while Sakura got stuck with Hag? Ino beams at him for it.
âI missed you, silly. Letâs go to the movies Friday, so you can make it up to me.â Ino says sweetly.
Sai turns to Sakura, âWhat do you think, Sakura? Shall we go?â
Ino glares at her, as if sheâs invited herself while Sakura puts her hands up in surrender.
âUm, actually Sai, I have training with Shikamaru on Friday night. I wonât be able to go.â Sakura lies.
âIs that what youâre calling it,â Ino grumbles under her breath.
âApologies, Ino. We will have to try another time.â He says to her.
âShe wonât mind if we go without her,â She says sweetly, then grinds out in a threatening tone, âRight, Sakura?â
âRight.â Sakura squeaks.
âAccording to my reading, the Hag is socially obligated to agree in this situation, though her true feelings could be to the contrary. It would be perceived as a slight to go without her.â Sai responds, looking rather proud at his insight.
Sakura cringes as Inoâs intensified glare.
âThen why donât you just bring Shikamaru along, Sakura.â Ino offers, âThen we can have a double date.â
Again, the way Ino says it give Sakura no room to disagree, but she does anyway.
âIâm not going on a double date.â She says firmly.
âForehead, letâs just talk for a second over there.â Ino says, grabbing her arm too tightly and dragging her out of hearing distance.
âDonât ruin this for me, Sakura. Iâm super close to sealing the deal on Sai and Iâm not about to give that up because you made some phony sisterhood pact to yourself to swear off men forever.â She whispers furiously.
âItâs not about my completely legitimate pact. I have way bigger things to worry about right now than going on a fake date.â Sakura hisses back. Danzoâs disappointed expression rises up in her memory, along with his gentle reminder of her deadline. She shakes her head, âAnd donât kid yourself, Ino. Sai has no idea youâre even interested in him.â
âThen you understand why I need this!â Ino argues back.
âEven if I wanted to, Iâd never get Shikamaru to agree to this.â Sakura says, trying a different angle.
âHa!â Ino lets out a shrill laugh, âThatâs what youâre worried about.â
Sakura glares, âYes. The last place heâd want to spend a Friday night is fourth-wheeling a date with you and Sai.â Sheâs not sure thatâs strictly true, but is hoping his lazy, reclusive track record works to her advantage.
âFourth-wheeling isnât a thing, and you know it.â Ino disagrees, âAnd heâd go if you asked him. Heâd show up in civilian clothes with his hair down if you asked him to.â
âYeah, right.â Sakura scoffs, but blushes at the image that pops in her head of him running a hand through his loose hair. She shakes her head and says with more bite than she means to, âIt doesnât matter who asks. The answer will be no.â
âThen youâd better convince him.â She says, jabbing a finger in Sakuraâs shoulder. âYou still owe me from the time I pretended to be your lover to get that stalker fan boy to stop bothering you.â
âHey, I didnât ask you do to that!â Sakura protests.
âSee, I did it out of the goodness of my heart, so nowâs your chance to repay me, because thatâs what girlfriends do.â She smiles with a shrug and turns back to Sai to answer without waiting for Sakura to respond.
âSai, sheâs in!â She giggles, skipping back over to him, âSee you Friday, Forehead!â
_____
Even though he said it wouldnât, Shikamaruâs waiting for her outside the theater out of uniform that Friday. His black pants look pretty much the same, but his well-toned arms are on full display in a mesh tee-shirt and a long green vest that brushes his thighs. It probably has the Nara clan symbol on the back.
âLook at you, Muscles,â She teases him, glancing pointedly at his exposed arms. He lets out an annoyed huff, but his cheeks go pink, âI thought you werenât wearing your civilian clothes tonight.â
âIt would have been more troublesome to stick out that to just change,â He sulks. She canât keep the smile off her face.
âIno and Sai here yet?â She looks around but doesnât see them.
âNot yet.â Heâs still blushing and looks to the side when he says, âYou look nice too.â
She lets out a surprised, âOh, thanks,â looking down at the outfit she found in the back of her closet. It had been hard to find something that was fancy enough to say âdateâ for Ino but casual enough to say âfriendsâ for Shikamaru. The simple cream tank top, with a more generous neckline than she was used to, tucked into a plain red skirt did the trick.
âForehead, Shikamaru!â Ino calls, jogging up with her arm looped through Saiâs.
âHere we go,â Shikamaru mumbles, pushing off the wall heâs leaning against.
âHey, none of that attitude,â She scolds. If she was taking a night off, it was going to be worth it, dammit, âWe are here to have fun. Even if it kills us,â
âIt just might,â he breaths out as Ino bounds up to them.
âYou actually showed up. I honestly didnât think you would,â Ino says with an obnoxious laugh. She eyes Inoâs crop top and short purple skirt and suddenly feels like her neckline isnât so racy after all. Saiâs outfit is just as bad, also in a black crop top with low riding pants.
âWhy am I the only one not wearing a crop top?â Sakura says pulling at the bottom half of her shirt.
âHey,â Shikamaru says sharply, gesturing to his shirt, âThis is not a crop top.â
âMight has well be,â She jokes, poking his abs through a hole in the mesh.
âStop that,â he complains, grabbing onto her hand.
âThis is going to be so fun!â Ino says, looping her arm through Sakuraâs and dragging them inside. Shikamaru doesnât let go of her hand until Ino pushes him and Sai into the line for tickets.
âWhy canât you just get your own stuff, Ino?â Shikamaru grumbles. âWhat a drag.â
âYouâd know why if you ever bothered to go on dates, Shikamaru.â She answers, sticking her tongue out at him. He flushes pink and glances shyly at Sakura.
âBeautiful is right. Traditionally men are the ones to pay for date activities,â Sai says, no doubt trying to be helpful.
âSheâs totally taking advantage of you, man,â Shikamaru says, shaking his head and turning to walk up to the counter.
âI donât understand,â Sai says, following behind him. âA date is still an equal exchange. Donât men usually receive payment in the form of sexual favors at the end of the night?â
Sakura hears Shikamaru let out a strangled groan. He grabs Sai by the back of the head and starts whispering something urgently to him.
She canât help but laugh at Shikamaruâs reaction.
âIsnât he the cutest?â Ino gushes. âHeâs like a lost little puppy.â
âHeâs something.â Is all Sakura can think to answer.
Inoâs eyes turn mischievous and swing to Sakura. âSo you got Shikamaru to come. Who was right again?â
Of course, Ino wanted to get in her I-told-you-so about it being relatively easy to get Shikamaru to come.
She tries to make it sound more trouble than it was. âYeah, well you donât know what I had to promise to get him to come here, Ino-pig.â
âOh my, Forehead!â Ino lets out a scandalized giggle. Sakuraâs face heats, realizing Ino took it sexually. âOn the contrary, I want to know every saucy detail.â
âItâs nothing like that!â Sakura says, but Ino is unphased.
âJust as long as itâs nothing naughty in the theater. Itâs all fun and games until youâre halfway through a hand job and a worker shines a flashlight on you with your hand down some guyâs pants in front of a theater full of judgy middle-aged women who clearly donât understand the concept of spontaneous romance.â
âThatâs so specific,â Sakura says suspiciously. âPlease tell me that didnât actually happen to you.â
âYes, well,â Ino waves of her comment, âLearn from my mistakes Sakura. But more importantly, donât mentally scar me by getting freaky with my teammate while Iâm 2 seats down.â
âI should say the same to you!â Sakura says, blushing further, but Ino doesnât make any promises.
Shikamaru and Sai return. Shikamaru looks more disgruntled than ever.
âThat was the most troublesome conversation Iâve ever had.â He grumbles under his breath to her, low enough for Sai and Ino to miss. But as Ino passes, he says, âYou owe me two times now for that.â
Sakura flushes. Although Sakura knows he means 2 weekends, Ino doesnât. She wiggles her eyebrows and Sakura wants to sink into the floor from embarrassment.
He hands her a ticket with âIllusion of Silenceâ written on the front, and she asks, âWhat are we seeing? A horror movie?â
âIt was that or a sappy romcom. Just remember I chose the lesser of two evils.â He says and takes her hand again, leading her to the theater. It feels a little strange to be holding hands, but she doesnât say anything. The trailers havenât started yet, so they have no trouble finding their seats. The theater is mostly empty anyway, probably not a good sign for the movie quality.
She sits down between Shikamaru and Sai.
âSakura, how is what you pass off as sketching going?â Sai asks.
Pass off. She suppresses the urge to smack him across the head. That kind of thing was frowned upon in these types of establishments.
âTerrible. I think Kurenai-sensei gave up on me.â
Kurenai had barely kept from laughing at Sakura when sheâd shown her sketch book. It was pitiful, and while there had been a small improvement in Sakuraâs visual genjutsu, Kurenai had decided to move on to a different topic. She still had to keep up the activity, but just not as her main focus.
Now they were working on non-visual genjutsu. Sakura found this a lot easier for some reason. Inducing pain, sounds, tastes, smells, all of that was just chemicals moving around the body. She understood those. Sheâd dealt with those before.
While sheâd been extremely glad for the change in topic, she couldnât manage to look forward to her lessons anymore. It was hard not to look at Kurenai differently after learning about her secret affair with Kakashi. It was a difficult feeling to explain, but every time she remembered it, her chest grew heavy, like something had reached inside her chest and squeezed a fist around her heart. She grits her teeth just thinking about it.
âI told you giving up was the best option,â Sai says sweetly, âNo reason to waste your time improving a hopeless skill.â
âShut up, Sai. A student is only as good as their teacher and you were absolutely no help.â She grumbles.
âHey, donât blame Sai because you can only draw stick figures. Some people just arenât born to be artists like he was,â Ino defends, sending a starry eyed look at Sai and resting a hand to Saiâs arm. Then she pulls him into a conversation about what his âartistic geniusâ has be working on lately.
âIs it really going that bad?â Shikamaru asks referring to her genjutsu training. His eyebrows are drawn in with concern.
âI donât know.â She grumbles. She doesnât want to admit it, but from Kurenaiâs reactions, she felt it was going that badly. She wasnât improving as fast as she should be. It seemed like something on a fundamental level just wasnât clicking. âI try to do what Kurenai is instructing, but it just doesnât seem to be working. We are so different that sometimes its hard to understand what she wants from me. Plus, it doesnât help that genjutsu is so subjective.â
âWhy donât we work on it together next week. It might help to get a fresh perspective.â
âReally? That would be amazing,â She says with a smile.
âOf course.â He takes her hand again, rubbing a thumb across the back.
âI donât know what Iâd do without you, Shikamaru.â She says, squeezing his hand back.
âLetâs not find out,â he jokes, try to be nonchalant but heâs beaming from the comment.
Sakura lets out a yawn, âLetâs not.â
âYouâre not going to fall asleep on me, are you?â He teases.
âNo, Iâm fine.â Sakura lies. Sheâd had practice with Team Guy this morning at 6am but had stayed up until 2am doing research. Physically, she was running out of steam fast. As the lights dim, she finds it harder and harder to keep her eyes open.
Shikamaru shakes her awake. Sometime during the opening credits, she fell asleep on his shoulder.
âOh, sorry,â She says, groggily. Then whispers, âWhat did I miss?â
âEverything,â he answers with a smirk.
âWhat?â She hisses, âWhy didnât you wake me up?â
He shrugs, âYou needed the rest. The point was to relax tonight, right?â
âI guess,â she grumbles.
âThe movie sucked anyway,â he says standing.
âThat was so scary!â Ino gushes to Sai. âIâm so glad you were here with me, Sai. I felt much safer.â
âIt was not really that scary, Beautiful. No reason to be afraid of pictures.â He says confused. Ino huffs.
As they leave, Ino insists on a walk in the park across the street, but within minutes, sheâs slipped off with Sai. The suggestive wink tells Sakura everything she needs to know about her plans.
Even just being friends with her, this was uncomfortable. Shikamaru actually was interested at some point. She wondered what he thought of all this.
âHow is this not extremely weird for you?â Sakura asks.
âWhat do you mean?â
âWell didnât you and Ino date a while back?â She explains and Shikamaru looks at her like sheâs grown a second head.
âTsh, no. Definitely not.â
âWell, you liked her though, right?â
Heâs pouting, and reluctantly says, âYears ago, maybe. It wasnât a big deal though.â
âBut you guys kissed.â She counters. That seemed like a pretty big deal to her.
He stiffens and goes bright red, âCan Ino not keep her mouth shut about anything?â
âSee, it is weird,â she says. But he doubles down.
âNo, itâs not.â He disagrees crossing his arms, âThat barely counts.â
But now sheâs picturing the worst. A grating feeling rises in her chest at the thought of Shikamaru and Ino kissing and she has a strange compulsion to ask just what counts as barely counting.
âBarely counts how?â She says. Sheâs not able to look him in the eyes, so she trains her gaze on an ice cream cart across the park.
âI dunno, it just does.â He shrugs.
âBecause it wasnât good?â She offers. She hopes it wasnât good.
âNo, it was good,â He says defensively.
âThatâs not what she saidâŠâ Sakura says skeptically, peaking at him out of the corner of her eye.
âWhatever,â Shikamaru grumbles. Heâs scowling, âI can kiss just fine. Sheâs just trying to cover up that sheâs the one who initiated the whole thing in the first place.â
âShe did?â This surprises her and somehow it makes a difference.
âI donât want to talk about this anymore.â Shikamaru states, picking up his pace. She strides right along undeterred.
âWell did you, like, want to kiss her?â
âI guess. Why does it matter?â
âBecause!â She canât seem to put the why into words. Itâs just a queasy feeling turning her stomach. Even though itâs not the full truth, she offers the explanation, âYou made out with your teammate, thatâs a big deal.â
He stops short and turns to fully face her.
âIt isnât a big deal and we didnât make out, okay.â He clarifies.
âThen what was it?â
âJust a kiss, Sakuraâ
âWell yeah, but was it a long, passionate kind -,â
âSo troublesome,â he grumbles into the sky.
âOr just a quick -,â
Sheâs cut off by a warm pressure on her lips and her mind goes blank. As soon as she realizes whatâs happening, itâs over.
Shikamaru pulls back a few inches, hands still cupping her face and searches her expression for her reaction. He kissed her.
âThatâs all it was.â He murmurs, eyes dark and voice low. Her breath catches in her throat, the queasy feeling in her stomach grows magnitudes greater.
âObviously Iâd do things a little differently now,â He murmurs and his eyes flash, daring her to ask just how.
She should say something, but she couldnât even if she wanted to. Her mind has snagged on the previous moment. The only additional thing she can seem to process is the warmth of his hands on her cheeks and his calming scent of pine and earth. Sheâs completely rooted in place by the heat in his chocolate brown eyes. It stokes something inside her. Maybe it is curiosity because she wonders what she would feel if just leans forward those few inches.
They bounce between her eyes and her lips, battling between waiting for her reaction and what she can only think to describe as desire. It only takes a few more moments for the latter to win.
He leans forward to capture her lips again, lingering longer this time. Its careful or rather experimental, testing her for a response she canât seem to give. Again, he pulls back, studying her face. Again, from the moment his lips touched hers, her mind is just wiped blank, unable or unwilling to process it. Whatever he finds in her expression is enough.
His hand slides to the back of her neck and he kisses her again, deeper. Her eyes slide shut without conscious thought. She feels his other hand ghost down her side, stopping at her waist and pulling her closer. Her hands go to his chest to brace herself.
The pressure has him pulling back, checking over her face. Heâs looking to see if sheâs asked him to stop, she realizes, and a gentle warmth settles in her stomach. This time, his lips brush softly against hers, begging her to return the pressure and its so sweet, so unsure, that she reacts without thinking, relaxing into him. He pulls her closer, tension she hadnât noticed draining from him and sighs against her mouth.
Finally, her thoughts are coming back to her, returning each slow, tender press of his lips against hers. The queasiness in her stomach settles into a gentle warmth and she relaxes into him. This is nice, she decides. Itâs comfortable. Not great, not terrible.
It different than sheâs ever felt before. Her heart isnât beating out of her chest, sheâs doesnât feel butterflies in her stomach and she isnât so caught up that needing air is secondary to feeling him against her.
Fine. Just fine.
Suddenly she thinks, shouldnât it be better than just fine? Shouldnât she be lit up inside, butterflies in her stomach, reluctant to separate even for air? The warmth in her freezes over.
âStop,â She gasps, pressing against his chest. He steps back, and the distance seems to return more of her mind to her. The ball of ice in her stomach grows colder.
What was she doing? This was Shikamaru. Her closest friend, and she needed him like she needed air. She couldnât do this. She couldnât get wrapped up in romance again and have everything between them fall apart. Because it would fall apart. Thatâs what love did to people or at least to her.
âThat was a mistakeâ She finally decides. It was a mistake and they could forget about it and move on like it never happened. But Shikamaruâs face falls. He looks scared, she thinks.
âDonât say that,â he begs, but she just shakes her head wrapping her arms around herself.
âI canât do this,â Then looks into his eyes which are breaking in front of her.
âYou donât have feelings for me,â he tries.
But thatâs not right. She felt something for him. He was so important to her and sheâd be lying if she hadnât found him attractive, but it didnât quite feel like love. At least not how sheâd loved Sasuke.
Even if it did, she didnât want that anymore. Love only led to heartbreak and loss and she couldnât lose him. Shikamaru was her only refuge in her storm of a life and she didnât know how sheâd stay afloat without him. Â
Words are pouring from her mouth, and sheâs not even sure they make sense, but she canât stop them.
âI-I donât know how I feel. I just â I canât lose you and if we do that, eventually weâll screw everything up and Iâll lose you. I just canât, Shikamaru. I canât. I need you.â
Hope shines in his eyes. Itâs a rejection, but not for the reason he feared. âYou wonât lose me.â
âI will.â She insists. Now sheâs the one thatâs scared. She torn between needing the comfort of his embrace and wanting to keep him at armâs length. She settles with taking a step closer and grabbing the opening of his vest. âYouâre the most important person in my life. I donât want anything to change between us.â
How can she explain it to him? How can she make him understand?
âNothing will,â He whispers, hand coming to her face again. But she can see the gears turning in his head. Heâs looking at her like a shogi piece now, something to outmaneuver, outthink to the outcome he wants. Anger flares up in her.
He strokes a thumb against her face, eyes settling again on her mouth.
âDonât,â She snaps, turning her face from his palm. She needed to leave. They just needed some time apart and heâd realize he was just caught up in the moment or something at theyâd put this behind them.
âI canât. I just need a minute.â She says disengaging from him and striding off.
âWait, Sakura!â he calls, but she doesnât. He swears under his breath.
She needed to put some distance between them, she needed to time to think, but she if she left alone, heâd just follow her. Ino and Sai approach then, Ino clinging to Saiâs arm. She doesnât want to talk with Ino, doesnât want her judgy questions, so she strides up to her next best option.
âSai, weâre getting ice cream,â She says, dragging him toward the stand across the part.
âSounds enjoyable,â He says with a smile, not at all minding the interruption.
Ino on the other hand lets out an annoyed, âHey!â but doesnât fight her past that. Sakura and Sai are out of earshot before she has a chance.
Ino crosses her arms, icily looking Shikamaru up and down.
âYou are really screwing this up, arenât you?â Ino says with a smirk.
Shikamaru scoffs going red and snaps, âLike youâre doing any better.â
To which Ino lets out an indignant âHmph!â
 -
Sakura stops in front of the ice cream cart and gets them both a chocolate cone. Eating her feelings sounded wonderful right now.
âShall we make some small talk now?â Sai asks with a smile. She groans.
âYou donât ask to make small talk, Sai. You just do it.â She explains, taking a lick of her chocolate ice cream. Its cold and sweet, but in a different way than Shikamaru had tasted.
Shit. Stop. That wasnât allowed.
âOkay, so what are you doing after this?â He asks and it sounds like a pick-up line he probably read from a book on interacting with females. She rolls her eyes. Still, sheâs thankful for the distraction and reminds herself this is still better than Ino.
âIâll probably go back to the archives tonight and finish reading a few documentsâ She answers, talking another taste of her ice cream. Sai steps in front of her and she stops short.
âDid you not find the message I hid for you?â He says looking worried.
âWhat message?â She asks, confused.
âThe one on the picture I gave you.â He says with a frown. Right, the picture of his brother. Is he talking about the numbers and symbol he signed in the corner? âYou should go straight home tonight, Sakura.â
âWhy would I do that?â she asks, growing annoyed that he wonât just get to the point.
âI cannot divulge that information.â He says robotically. She freezes.
âWhat did you just say?â she asks him to repeat.
âI cannot divulge that information.â He repeats and his eyes look urgent. Itâs the phrase he uses when heâs close to triggering his seal. The message was about Danzo.
âSai, whatâs the message? What do you mean?â She grabs in shirt and pulls him to her, but he canât answer.
âI cannot divulge -,â
âI get it!â She snaps at him. She has to ask it differently and her mind is racing a mile a minute over the possibilities.
âYou said I shouldnât go to the archives, right?â She tries, going back over his words.
âYes, you should just stay home tonight.â He repeats.
âSo, the message has something to do with the archives?â
âI cannot divulge -,â he begins.
âSo, Iâm right? You canât tell me because Iâm right.â She deduces quickly. âThe message is about the archives. Is it a clue? Can I find it in the archives?â
âI cannot divulge that information.â He says, but this time seems to fight against it. âDonât go there, Hag. You shouldnât -,â
âStop calling me Hag!â She bites out, unable to sensor herself, âI donât care what I should or shouldnât do. Iâm going.â She releases his shirt and starts down the road.
âWait!â He grabs her arm, âListen, you shouldnât -,â
âWas it important? Your message?â She interrupts.
âYes,â he says, âbut -,â
âThen Iâm going to find it!â She says pulling her arm from his grasp and shoving her ice cream cone into it instead. Sheâs determined and sprints down the path. Sai had finally given her a clue about Danzo, and sheâs not going to let this piece of information slip away.
âItâs not safe!â he calls, but sheâs already disappeared into the night.
Reading this, I feel like this was better...hahaha oh well.
3 notes
·
View notes
Text
Ok. AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAA !
Just yesterday I was talking about how my favorite FR feature is the humble bio box and it is revamped. It is brand new!!
Okay, scenes: I love this. I love the concept. I think that the pillowy Swipp one would suit Profit super well, sheâs such a hedonist, haha. I need Autumn Clearing for Huckleberry. Foxfire Grove for Four Lips dragons and the Shoreline one for Salt Forkers... Iâm gonna be broke. Iâm broke already but Iâm gonna be broker.
My one thing (itâs not a complaint, itâs not a gripe, itâs just me) is my âLoreâ dragons, the ones with just setting info, not actual characters. What I do, or what I did, was get my hands on a full-coverage skin of some kind and make just do that. Like, Salt Fork lore is a beach skin. Square Toe is a desert skin. Is a custom desert skin, which on the one hand it looks awesome but on the other hand an invisibility cloak and an appropriate scene would be so much better but invisibility cloaks are EXPENSIVE. And itâs not like I could sell the custom bc itâs barely a custom- I was just the only person on the print list for like a year so I got super impatient and gave the guy a blueprint. No one else is gonna want to buy it.
...Altho this is barely a problem bc so far none of the vistas match my vision exactly for any settings. I guess I just gotta wait and see what else comes out new.
The new layout looks a little weird to me but Iâm sure I just need to get used to it. Itâs a lot sleeker and has a lot better buttons. That one to go directly to the scrying workshop is gonna be a lifesaver. And we can feed individually now! Hallelujah
Familiars donât usually factor into my lore so naming them isnât gonna be a huge thing for me but for people who do, congrats!! Altho now I can do this I might factor them into my lore more- it just felt awkward having someone purportedly be a character but onsite itâs just a species name. Still, Laviniaâs nekomata has always been named Pumpkin and Rhondaâs always been a valued member of the circus so now theyâll look like it
Vistas in the bio box? Amazing. I love it!! definitely gonna have to experiment in some fodder bios before I risk messing with all my fancy coded bios but if I can make it look good I 100% want to do it for everybody. Also, will it be all vistas unlocked on your account? Or if you want twelve dragons with, say, Training Fields II, do you need twelve copies of Training Fields II? Bc that would be interesting. Bring the prices up maybe?
And the list of refactors at the end made me so happy, so much has been done already! And Iâm really looking forward to most of the stuff left to do! Iâm especially interested in Festive Favors, because I have no idea what kind of improvements you could make with it. I barely even think about it, itâs just... one week of the month itâs there and then nothing else. Iâd love new Joxar art though!
2 notes
·
View notes
Text
Winston Programming Headcanons
hi Iâm here to dump WAY too many headcanons for how Winston works. please talk to me about them. i beg of u guys,,,,
he's one of those people on stack overflow who marks your question as duplicate, closes it, and links you to another post that doesn't answer your question. and it's instantaneous because he has a Fuckload of points on that hellhole site.
he likes Matlab :/
but he also definitely is in the arrays begin at 0 camp like any sane person is
he's on the spaces side for tabs vs spaces, but he'll use soft tabs (tabs that turn into spaces)
brackets on the same line kinda guy (heâs wrong but thatâs who he is)
he uses all the languages he mentioned in the math meetup scene but his favorite language is python because of its hella Dope math library (shoutout to math.py, i never fuckin use it)
second favorite is C. he loves the power of direct memory manipulation for getting into the Nitty Gritty. and he's not afraid to bust out assembly.
but because he switches between those two a lot, semicolons (or the lack thereof) fucks him over frequently
he uses vim. like he really uses vim. he's got one of those colored keyboards with the popular shortcuts and commands on it. his vimrc file is something he custom wrote and heâs Very Proud of it. heâs got the whole custom highlighting thing going on.
this man cannot survive without his Multitude of bash scripts.Â
watching him try to work on someone elseâs computer is like watching a baby try to walk. his setup is so specific to him and what he needs to work that anything else just Doesnât Work for him. heâll try to do one of the shortcuts heâs set up that heâs so used to and nothing happens and heâs just :o
at least one of his six monitors is always just playing random youtube/netflix stuff in the background as he works, but as soon as he really really needs to focus he turns it off so he can figure stuff out.Â
frantic whiteboard pseudocoding as he tries to map out what he sees in his head for other people to understand or before he loses it. his handwriting is messy and barely legible. there are 5 expo markers laying around on his desk, all of which are shitty and out of ink, but he forgets to get new ones. he loves those white board desks and heâs shoved everything off a desk before so he can write on it.Â
writes down bits of code on whatever he can when he figures out how to do something that heâs been stuck on
if heâs having a particularly hard time on something at the moment, he tries to take a break but it still Consumes his thoughts. he angrily paces around the Quant Dungeon a lot, trying to calm down but Failing.
spends Hours Not Reading The Documentation and then getting angry when he finally resigns looks at it and it solves all his problems
he likes watching those videos on youtube that visualize all the different sorting algos (i really,,,, really,,,,, like doing this) ((idk maybe he does this as a visual stim maybe))
favorite data struct is leftist heaps. he likes the organized balance.
favorite sorting algo is merge sort because he likes seeing all the elements being broken down and then coming back together, in an organized order.
he uses Arch, btw. (im sorry please donât kill me for this im very sorry)
he judges you based on what Linux distro you prefer, all while knowing people judge him the Most for using Arch.
he goes to meetup.com programming meetups and tries and fails to make friends
heâs in the ACM special interest group for econ and computation
if god forbid he has to pair program, heâs the most MISERABLE motherfucker to work with. if heâs the one driving, he wonât listen to any suggestions and if heâs the one watching, then heâs backseat programming the entire time.Â
he's not into hacktivism personally but he likes reading about it and knowing the Lore as well as reading about cybersecurity/penetration testing
he definitely submits memes to r/programmerhumor and then also complains that the subreddit is too general
he likes what he does but he doesn't usually program off the clock. but sometimes he'll get an idea for a personal project!!
his has exactly one personal project at a time. it either gets finished or it doesnât before he moves onto the next one.
his personal GitHub is silent for months and then suddenly for a week straight it's dark green before fading into silence again
doesnât like working from home. he really needs the separation between his work space and his living space.
very cryptic and unhelpful commit messages. when trying to roll back he hates himself because he has no IDEA what him in the past meant by ânode updated,â because WHAT IN THE NODE WAS UPDATED??? he didnât write it down and now itâs been two months since heâs looked at this code and he has no fucking clue.
names his variables funky things, also causing trouble for himself down the line.Â
sometimes leaves a dangling else statement when he writes an if, as if daring the if statement not to execute
leaves funny comments for himself in his code and other non helpful comments for whoever has to work on his code/maintain it after him. literally all sorts of remarks except for describing what his code actually does. job security! until he forgets how the fuck he did something, which is honestly only like two months later.
has definitely done the â//donât touch, this works by magicâ comment and the â//donât refactor and come crying to me when it breaksâ comment
this is probably his second real job out of college. he reads early-mid 20s to me, and so heâs definitely doing that comp sci thing where you hop around companies every few years to get a massive pay raise.Â
i think he only has his bachelorâs degree, but he definitely went to cornell. double major in comp sci and math. or comp sci and econ. definitely possible he has his masters though. i think if so he went to upenn for it and focused on the econ side there.
his internship during college is at a place that works with the math behind computer graphics. he loves matrices. heâs working for the fun of it before he gets down to business after he graduates.
his first job out of college is as a data analyst.Â
likes writing code to make fancy/fun graphics for his statistics/results in presentations to his bosses. if he has the time. which he usually doesnât.
"blockchain is just a fancy linked list" he says, as he makes a killing investing in cryptocurrency so he graduates with minimal debt.
he has a "the cloud is just someone else's computer" graphic t shirt
he's very into getting the most optimal run time for in his code, which is part of what makes his algo for tmc so Good. everything needs to run as As Fast As Possible in that algo. Time Complexity Is His Jam. idk what to tell u. the dude loves math.
but also he just wrote a quad nested for loop and this is the comment above it:Â //This is O(scary), but seems quick enough in practice
space complexity? not so much. he doesnât care about how much space his algos take up.Â
he hates maintaining code. heâs itching to create new things and he views programming as a sort of art and creative expression sometimes (im right on this. programming is creative and ill fight to the death).
#winston billions#billions#because I'm a comp sci major and i gotta project#idk please someone talk to me about these#do like the 5 people on this site who care about winston care about how he works#im not actually really projecting tbh#a good amount of these dont apply to me#i just counted im only like 14 of these#okay that SOUNDS like a lot but theres around 50 of these bullet points#anyways im releasing this out into the world#at 2:30 am which is totally the best time and the time people are awake#but ALSO i would totally fair in projecting#i got winston when i took that jammin quiz nothingunrealistic made#but no i think winston and i would have very different work styles#and hey if no one cares about this at least i had fun#which really is all that matters in the end#my posts
16 notes
·
View notes
Text
Creating Sortable Tables With React
Sorting the table has always been a rather difficult problem to get right. To keep track of, detailed
DOM
mutations to do and even complex sorting algorithms, there are a lot of interactions. It is only one of those obstacles which is difficult to get correct. Exactly right?
Instead of pulling out into external libraries, let's try making things ourselves. We will be building a reusable way to sort your tabular data in React in this post. We will go through every move in detail, and learn along the way a bunch of useful techniques.
We're not going to go through basic
React
or JavaScript syntax, but to follow along, you don't have to be an expert in reacting.
Creating A Table With React
Sorting The Data If you would believe all the interviewers on the whiteboard, you would think that software engineering has been almost all sorting algorithms. Fortunately, we're not going to look into a short type or type of bubble here.
Data sorting in JavaScript is quite straightforward, thanks to the sort) (function of the built-in array. Without an extra argument it will sort arrays of numbers and strings:
const array = ['mozzarella', 'gouda', 'cheddar']; array.sort(); console.log(array); // ['cheddar', 'gouda', 'mozzarella']
If you want something a bit cleverer, a sorting function may be passed. This function is given as arguments to two things in the list, and positions one in front of the other based on what you decide. Let's start by sorting out the data by name which we get alphabetically.
What's happening here, then? First, we create a copy of the prop products, which we can change and modify as we please. We need to do so because the method Array.prototype.sort replaces the original list, rather than returning a new sorted copy.
Making Our Table Sortable
So now we can make sure that the table is sorted by name, but how can we alter the sorting order ourselves?
We need to recall the field currently sorted to adjust by which field we sort by. We are going to do that with the useState fork.
A hook is a special form of feature that enables one to "hook" into some of the key features of React, such as state control and triggering side effects. This specific hook allows us to retain, and alter, a piece of internal state in our component if we like. That is what we will be adding:
const [sortedField, setSortedField] = React.useState(null);
We start by doing no sorting at all. Next, let's modify the table headings to include a way of changing by which field we want to sort.
Now, whenever we click the heading of a table, we update the field we want to sort by. Neat-o-o! However, we are still not doing any real sorting, so let's resolve that. Mind the algorithm of previous sorting? Here it is, altered only slightly to fit with some of our field names.
Ascending Vs Descending
The next feature we would like to see is a way to switch from ascending to descending order. By clicking the table heading one more time, we will switch between ascending and descending order. We'll need to add a second piece of state to execute this â the sort order. To retain both the name of the field and its direction we must refactor our current sortedField state variable. This state variable will contain an object with a key (the field name) and a path, rather than a string. To be a little simpler we will rename it to sortConfig.
Now, if the course is 'ascending' we're going to do as we have done before. If it is not, we are going to do the reverse, giving us a downward direction. Next we will create a new function â requestSort â that will accept the name of the field, and update the state accordingly.
Now we are starting to look pretty feature-complete, but one big thing still remains to be done. We need to ensure we sort our data only when we need it. We are currently sorting out all our data on every render, which will lead to all kinds of performance problems down the line. Let's use the built in Memo hook instead to memorize all the slow bits!
If you haven't seen it before, useMemo is a way to archive costly computations â or memoize them. So given the same data, if we re-render our component for some purpose it doesn't have to sort the products twice. Notice that if our goods change we want to cause a new type, or the field or path we sort by changes. Wrapping our code in this feature will have major consequences for the efficiency of our table sorting!
Making It All Reusable
One of the best things about hooks is how simple it is to make reusable reasoning. You 're likely to be juggling all types of tables in your submission, and having to re-implement the same stuff sounds like a drag again. React has the functionality called custom hooks. They sound fancy but they're all standard features that use other hooks inside. Let's refactor our code to include in a custom switch, so that we can use it anywhere!
This is pretty much copy and paste from our previous code, with a bit of renaming thrown in. useSortableData accepts the items, and an optional initial sort state. It returns an object with the sorted items, and a function to re-sort the items.Our table code now looks like this:
A Last Touch
Wrapping Up
As it turns out, after all, building your own table sorting algorithm was not an unthinkable task. We found a way to model our state, we wrote a generic sorting function and we wrote a way of updating what our preferences for sorting are. We ensured everything was performing and refactured everything into a custom hook. Finally, we've provided the user with a way to show the sort order.
As a reputed Software Solutions Developer we have expertise in providing dedicated remote and outsourced technical resources for software services at very nominal cost. Besides experts in full stacks We also build web solutions, mobile apps and work on system integration, performance enhancement, cloud migrations and big data analytics. Donât hesitate to
get in touch with us!
#b2b website#b2b ecommerce b2b content marketing b2b seo b2b market research companies b2bservices Ecommerce#b2b ecommerce b2b content marketing b2b market research companies b2b seo b2bservices Ecommerce
0 notes
Text
Creating Sortable Tables With React
Sorting the table has always been a rather difficult problem to get right. To keep track of, detailed DOM mutations to do and even complex sorting algorithms, there are a lot of interactions. It is only one of those obstacles which is difficult to get correct. Exactly right?
Instead of pulling out into external libraries, let's try making things ourselves. We will be building a reusable way to sort your tabular data in React in this post. We will go through every move in detail, and learn along the way a bunch of useful techniques.
We're not going to go through basic React or JavaScript syntax, but to follow along, you don't have to be an expert in reacting.
Creating A Table With React
Sorting The Data If you would believe all the interviewers on the whiteboard, you would think that software engineering has been almost all sorting algorithms. Fortunately, we're not going to look into a short type or type of bubble here.
Data sorting in JavaScript is quite straightforward, thanks to the sort) (function of the built-in array. Without an extra argument it will sort arrays of numbers and strings:
const array = ['mozzarella', 'gouda', 'cheddar']; array.sort(); console.log(array); // ['cheddar', 'gouda', 'mozzarella']
If you want something a bit cleverer, a sorting function may be passed. This function is given as arguments to two things in the list, and positions one in front of the other based on what you decide. Let's start by sorting out the data by name which we get alphabetically.
What's happening here, then? First, we create a copy of the prop products, which we can change and modify as we please. We need to do so because the method Array.prototype.sort replaces the original list, rather than returning a new sorted copy. Making Our Table SortableSo now we can make sure that the table is sorted by name, but how can we alter the sorting order ourselves?
We need to recall the field currently sorted to adjust by which field we sort by. We are going to do that with the useState fork.
A hook is a special form of feature that enables one to "hook" into some of the key features of React, such as state control and triggering side effects. This specific hook allows us to retain, and alter, a piece of internal state in our component if we like. That is what we will be adding:
const [sortedField, setSortedField] = React.useState(null);
We start by doing no sorting at all. Next, let's modify the table headings to include a way of changing by which field we want to sort.
Now, whenever we click the heading of a table, we update the field we want to sort by. Neat-o-o! However, we are still not doing any real sorting, so let's resolve that. Mind the algorithm of previous sorting? Here it is, altered only slightly to fit with some of our field names.
Ascending Vs DescendingThe next feature we would like to see is a way to switch from ascending to descending order. By clicking the table heading one more time, we will switch between ascending and descending order. We'll need to add a second piece of state to execute this â the sort order. To retain both the name of the field and its direction we must refactor our current sortedField state variable. This state variable will contain an object with a key (the field name) and a path, rather than a string. To be a little simpler we will rename it to sortConfig.
Now, if the course is 'ascending' we're going to do as we have done before. If it is not, we are going to do the reverse, giving us a downward direction. Next we will create a new function â requestSort â that will accept the name of the field, and update the state accordingly.
Now we are starting to look pretty feature-complete, but one big thing still remains to be done. We need to ensure we sort our data only when we need it. We are currently sorting out all our data on every render, which will lead to all kinds of performance problems down the line. Let's use the built in Memo hook instead to memorize all the slow bits!
If you haven't seen it before, useMemo is a way to archive costly computations â or memoize them. So given the same data, if we re-render our component for some purpose it doesn't have to sort the products twice. Notice that if our goods change we want to cause a new type, or the field or path we sort by changes. Wrapping our code in this feature will have major consequences for the efficiency of our table sorting! Making It All ReusableOne of the best things about hooks is how simple it is to make reusable reasoning. You 're likely to be juggling all types of tables in your submission, and having to re-implement the same stuff sounds like a drag again. React has the functionality called custom hooks. They sound fancy but they're all standard features that use other hooks inside. Let's refactor our code to include in a custom switch, so that we can use it anywhere!
This is pretty much copy and paste from our previous code, with a bit of renaming thrown in. useSortableData accepts the items, and an optional initial sort state. It returns an object with the sorted items, and a function to re-sort the items.Our table code now looks like this:
A Last Touch
Wrapping UpAs it turns out, after all, building your own table sorting algorithm was not an unthinkable task. We found a way to model our state, we wrote a generic sorting function and we wrote a way of updating what our preferences for sorting are. We ensured everything was performing and refactured everything into a custom hook. Finally, we've provided the user with a way to show the sort order.
As a reputed Software Solutions Developer we have expertise in providing dedicated remote and outsourced technical resources for software services at very nominal cost. Besides experts in full stacks We also build web solutions, mobile apps and work on system integration, performance enhancement, cloud migrations and big data analytics. Donât hesitate to
get in touch with us!
0 notes
Text
Problem solving with Safia: the optimizerâs dilemma
I have a confession to make.
I'm getting pretty bored of reading the Node codebase.
I know, I know. I've only been doing it for about three weeks now, but what can I say? I've got a rather short attention span. Maybe I'll get back to it at some point, but for now, I'd like to try some different things.
I was recently reminiscing about some of the things I liked doing when I first started coding in my teens. As it turns out, I liked solving some of the problems on Project Euler. In fact, I kept a little blog where I maintained the solutions for the problems that I was solving. I will avoid linking to that blog here because some things just need to die in obscurity.
Anyway, I figured that I would pick up where I left off and start solving some of the problems here and live-blogging my solutions as I write them.
It turns out that the last problem that I solved (or at least publicly blogged about the solution for) was problem 22 back in September of 2012. That would've been the start of my sophomore year in high school. Feels like centuries ago!
So with that in mind, I figured that I would start, six years later, by working on the solution for problem 23. It goes a little something like this.
A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.
A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.
As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.
Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.
Alright! So the main goal here is to find the sum of all positive integers that cannot be written as the sum of two abundant numbers. The problem text also tells us that every number greater that 28,123 can be writtern as the sum of two abundant numbers. So this narrows down our search space to numbers between 0 and 28,123. That's a pretty large search space, although we have these things called computers that are stupid and fast and we can put them to work!
I'll admit that I used to be the kind of programmer who would sit and look at problems like these and try to cook up a clever solution right away. But I got older (and wiser) and realized that in most cases, you'd be totally find just throwing a for-loop at the problem. So I created a quick little template for what the solution would look like.
def abundant_terms_for_sum(x): fancy math stuff that I'm unsure of yet def non_abundant_sums(): total = 0 for x in range(28123): if not abundant_terms_for_sum(x): total += x return total
Pretty basic, right?
Side note: I'll be using Python 3 to solve these problems. That's the same programming language I used to solve them when I was a teenager. Although looking back at my blog, I solved some of them using Common Lisp. Maybe I'll take a crack at doing that now!
Now, since I first started solving these problems in my sophomore year of high school, I've had about 6 years of advanced algebra and calculus classes taught to me. That being said, I still have no clue what I'm doing when it comes to math. So I headed over to the good ol' trusty Google dot com to see if someone who liked numbers way more than me had figured out a clever way to determine whether a number could not be the sum of two abundant numbers.
Side note: If you can't be clever yourself, you can always leverage another person's cleverness!
I couldn't find anything useful on the Internet, so it turns out I'll have to use my own noggin for this one. I suppose the point of these problems is to put the noggin to work anyways...
So, my general strategy for things like this is to create an outline of the program with a scaffold of all the functions that I think I might need to call.
def generate_abundant_numbers(): create a list of the abundant numbers less than 28123 ABUNDANT_NUMBERS = generate_abundant_numbers() def abundant_terms_for_sum(x): for num in ABUNDANT_NUMBERS: difference = x - num if difference in ABUNDANT_NUMBERS: return True return False def non_abundant_sums(): total = 0 for x in range(28123): if not abundant_terms_for_sum(x): total += x return total
So basically, my plan is to generate a list of all the abundant numbers that are less than the boundary we set at 28,123 in a global called ABUNDANT_NUMBERS. Then, the abundant_terms_for_sum function will check if the terms of the sum of x are in ABUNDANT_NUMBERS and handle it appropirately. The only unfilled function here is the generate_abundant_numbers function. I did some hacking around to figure out if I could implement something using for-loops and mathy-math and came up with the following.
def get_proper_divisors(n): divisors = [] for x in range(1, n + 1): if n % x == 0 and n != x: divisors.append(x) return divisors def generate_abundant_numbers(): numbers = [] for x in range(28123): proper_divisors = get_proper_divisors(x) if sum(proper_divisors) > x: numbers.append(x) return numbers
Now, this piece of code took so long to run, I had to trim my hair by the time it was done running. Well not really, I actually ended up just halting it as it was checking the 93rd number but you get the gist.
The big culprit here is the fact that there are two iterations that go from 0 to 28123 so the time complexity (oh gosh, did I just use those words?!!?) of this particular implementation is O(n^2).
If this was a technical interview, this is the point where I would stare blankly at the screen and babble out my stream of concious to the poor person on the other end of the phone. Since I'm just doing this alone in my bedroom, I'm going to stare really hard at the code until some revelation hits me through some form of air-based diffusion.
Just stare really hard.
Keep staring.
And thinking.
So there are a few things that I can do here. The problem statement that 12 is the smallest abundant number. So I updated my code to refelct this.
def generate_abundant_numbers(): numbers = [] for x in range(12, 28123):
The next thing I realized was a problem with my abundant_terms_for_sum function. When iterating through each of the ABUNDANT_NUMBERS I needed to do a better job of skipping throug the abundant numbers I knew for sure were not part of the solution.
def abundant_terms_for_sum(x): for num in ABUNDANT_NUMBERS: if num > x: return False difference = x - num if difference in ABUNDANT_NUMBERS: return True return False
With these changes, I noticed that the program was running much, much faster. I hadn't actually done anything to alter the time complexity of the implementation, but the minor changes I made helped improve the run-time for the average case that I was dealing with.
At this point, I actually decided to let the program run all the way through. I still hadn't actually verified that my implementation was correct, so it was kind of silly for me to be working on optimizing something that might not have been totally accurate.
So I let this rather slow code run for a little bit while I went out and pretended that I wasn't really a robo â errr, while I cleaned up my apartment.
Once it was done running, I pasted the answer I got into the checker and found out I was correct. What a relief! Now I can do some more optimizations without
The next thing I did was make some improvements to the way that proper_divisors and generate_abundant_numbers worked. Overall, these changes reduce the space complexity of the program since I'm directly computing the sum of the proper divisors instead of storing the divisors in an array and then summing them up. This helped a little bit because as it turns out the time complexity of the sum function in Python is O(n).
def get_proper_divisors(n): total = 0 for x in range(1, n + 1): if n % x == 0 and n != x: total += x return total def generate_abundant_numbers(): numbers = [] for x in range(12, 28123): sum_proper_divisors = get_proper_divisors(x) if sum_proper_divisors > x: numbers.append(x) return numbers
Side note: I know I'm using the words time complexity a lot and it might be scary if you are a new programmer. You can read more about what time complexity is here or here but basically it is just a fancy way of answering the question "How long will this program take to run?"
The next thing I did was refactor the non_abundant_sums function to take advantage of list comprehensions.
def non_abundant_sums(): return sum([x for x in range(28123) if not abundant_terms_for_sum(x)])
So, my current solution thus far looks like this.
def get_proper_divisors(n): total = 0 for x in range(1, n + 1): if n % x == 0 and n != x: total += x return total def generate_abundant_numbers(): numbers = [] for x in range(12, 28123): sum_proper_divisors = get_proper_divisors(x) if sum_proper_divisors > x: numbers.append(x) return numbers ABUNDANT_NUMBERS = generate_abundant_numbers() def abundant_terms_for_sum(x): for num in ABUNDANT_NUMBERS: if num > x: return False difference = x - num if difference in ABUNDANT_NUMBERS: return True return False def non_abundant_sums(): return sum([x for x in range(28123) if not abundant_terms_for_sum(x)]) print(non_abundant_sums())
To be honest, it is still pretty hecking slow.
First and formost, the get_proper_divisors function takes a really long time to run. I optimized it using a pretty common optimization for factorization algorithm that relies on one of the properties of the factors of a number.
def get_proper_divisors(n): limit = math.sqrt(n) if limit.is_integer(): total = -limit else: total = 1 for x in range(2, int(limit) + 1): if n % x == 0: total += x + int(n / x) return total
The next thing I did was remove the reliance on abundant_terms_for_sum and just use Python's any function to check if there were any abundant terms that added up to a particular sum.
def non_abundant_sums(): total = 0 for x in range(28123): if not any((x - i in ABUNDANT_NUMBERS) for i in ABUNDANT_NUMBERS): total += x return total
Despite these changes, the program was still running a bit slow. Specifically, there were two for-loops in the code that iterated up to 28,123, the one in non_abundant_sums and the one in generate_abundant_numbers. I decided to combine these two functions together and avoid pre-allocating the dependent numbers. I also ended up using a set to store the date because I realized that we don't care much to have duplicate summation entries in our data set.
def non_abundant_sums(): total = 0 numbers = set() for x in range(28123): if get_proper_divisors(x) > x: numbers.add(x) if not any((x - i in numbers) for i in numbers): total += x return total
Sweet! Now the program runs a little faster. Here's the final code for the curious.
import math def get_proper_divisors(n): limit = math.sqrt(n) if limit.is_integer(): total = -limit else: total = 1 for x in range(2, int(limit) + 1): if n % x == 0: total += x + int(n / x) return total def non_abundant_sums(): total = 0 numbers = set() for x in range(28123): if get_proper_divisors(x) > x: numbers.add(x) if not any((x - i in numbers) for i in numbers): total += x return total print(non_abundant_sums())
So basically, I started off writing a lot of very simple code then I shaved a ton of it off. This is usually how things go for me when I'm solving problems. Just dump whatever I can onto the screen and then see if I can make it better!
There's a big life lesson in there somewhereâŠ.
1 note
·
View note
Text
What Is Redux: A Designerâs Guide
What Is Redux: A Designerâs Guide
Linton Ye
2018-07-05T15:30:46+02:002018-07-10T12:05:47+00:00
Have you heard of Redux? What is it? No googling, please!
âFancy backend stuff.â
âI have heard of it, but Iâm not aware of what it is. Itâs a React framework perhaps?â
âA better way to store and manage states in a React application.â
Iâve asked this question to over 40 designers. The above are their typical answers. Many of them are aware that Redux works with React and its job is âstate management.â
But do you know what this âstate managementâ really means? Do you know Reduxâs real power is beyond managing the state? Do you know that Redux doesnât necessarily require React to work? Do you want to join your teamâs discussion (or at least lunch chats) about whether to use Redux? Do you want to design with an understanding of how Redux works in mind?
With the help of this article, Iâd like to show you a full picture of Redux: what it can do, why it does its things, what the downsides are, when to use it, and how it relates to design.
My goal is to help designers like you. Even if you havenât written a single line of code before, I think itâs still possible and beneficial (and fun) to understand Redux. Expect plain English and doodles â no code or abstract talks.
Ready for the ride?
With so much happening on the web, what should we really pay attention to? At SmashingConf New York 2018 đșđž weâll explore everything from PWAs, font loading best practices, web performance and eCommerce UX optimization, to refactoring CSS, design workflows and convincing your clients. With Sarah Drasner, Dan Mall, Sara Soueidan, Jason Grigsby, and many other speakers. Oct 23â24.
Check the speakersÂ ïżœïżœ
What Is Redux?
At a super-high level, Redux is a tool that developers use to make their lives easier. As many of you might have heard, its job is âstate management.â Iâll explain what state management means a few sections later. At this point, Iâll leave you with this picture:
Redux manages state, but in the background, there are a few hidden powers. (Illustration by Beebee) (Large preview)
Why Should You Care?
Redux is more about the inner workings of an app than its look-and-feel. Itâs a somewhat complex tool with a steep learning curve. Does that mean we, as designers, should stay far away from it?
No. I think we should embrace it. A car designer should understand what the engine is for, right? To successfully design app interfaces, designers should also have solid knowledge about things under the hood. We should learn about what it can do, understand why developers use it, and be aware of its advantages and implications.
âDesign is not just what it looks like and feels like. Design is how it works.â â Steve Jobs
What Can Redux Do?
Many people use Redux to manage the state in React apps. Itâs the most common use case in the wild and Redux improves the aspects where React doesnât do well (yet).
However, youâll soon see that the real power of Redux goes way beyond that. Letâs get started by learning what state management really means.
State Management
If you are not sure what this âstateâ means, letâs replace it with a more generic term: âdata.â State is data that change from time to time. State determines whatâs displayed on the user interface.
What does state management mean? In general, there are three aspects of data that weâd need to manage in an app:
Fetching and storing data
Assigning data to UI elements
Changing data
Letâs say we are building a Dribbble shot page. What is the data we want to display on the page? They include the authorâs profile photo, name, the animated GIF, the number of hearts, the comments, and so on.
Data on a Dribbble shot page (Large preview)
First, we need to fetch all these data from a server in the cloud and put it somewhere. Next, we need to actually display the data. We need to assign pieces of this data to corresponding UI elements that represent what we actually see in the browser. For example, we assign the URL of the profile photo to the src attribute of an HTML img tag:
<img src='https://url/to/profile_photo'>
Finally, we need to handle changes to the data. For example, if a user adds a new comment to a Dribbble shot, or adds a star, we need to update the HTML accordingly.
Coordinating these three aspects of state is a big part in front-end development, and React has various degree of support for this task. Sometimes the built-in facility in React works well enough. But as the app grows more complex, its state may become harder to manage with React alone. Thatâs why many people start using Redux as an alternative.
Fetching And Storing Data
In React, we break down a UI into components. Each of these components can be broken down into smaller components (see âWhat is React?â).
Dribbble shot page broken down into components (Large preview)
If our UI is structured this way, when do we fetch the data and where to store it before populating the UI?
Imagine thereâs a chef living in each component. Fetching data from servers is like sourcing all the ingredients needed to prepare dishes.
A naive way is to fetch and store the data where and when itâs needed. This is like each chef going out to buy vegetables and meats directly from far-away farms.
The naive way: fetch data from each component. (Illustration by Beebee) (Large preview)
This approach is wasteful. Weâd need to call the server many times from many components â even for the same data. The chefs would waste a lot of gas and time traveling back and forth.
With Redux, we fetch data once and store it in a central place, conveniently called âstore.â The data is then ready for use anytime by any component. This is not unlike having a superstore nearby where our chefs can buy all the ingredients. The superstore sends trucks to carry back vegetables and meats in bulk from farms. Itâs a lot more efficient than asking individual chefs to go to the farms themselves!
The store also serves as the single source of truth. Components always retrieve data from the store, not from anywhere else. This keeps all the UI content consistent.
Redux as a central store of data. (Illustration by Beebee) (Large preview)
Assigning Data To UI Elements
With only React, thereâs actually a better way to fetch and store data. We can ask our very kind chef Shotwell to do the shopping for all his chef friends. He would drive a truck to the farms and carry back the goodies. We could fetch data from a container component, for example, the âShotâ component in the Dribbble example, and use that as the single source of truth.
Fetch data from the root component. (Illustration by Beebee) (Large preview)
This approach is more efficient than the naive way of fetching data from every component. But how does Shotwell pass the ingredients to other chefs? How to pass the data to the components that actually render HTML elements? We pass data from outer components to inner components like the baton in a relay, all the way until the data reach the destination.
For example, the URL of the author avatar needs to be passed from âShotâ, to âShotDetailâ, to âTitleâ and finally to the <img> tag. If our chefs live in an apartment, it really looks like this:
Pass data to components via props. (Illustration by Beebee) (Large preview)
To deliver data to the destination, weâd have to engage all the components on the path, even if they donât need the data at all. Itâd be really annoying if there are many floors!
What if the superstore does door-to-door delivery? With Redux1, we can plug in any data into any component, without affecting other components at all, like so:
1 To be absolutely accurate, itâs another library called react-redux that hands data to React components, not Redux itself. But since react-redux just does the plumbing and people almost always use Redux and react-redux together, I think itâs fine to include this as one of the benefits of Redux.
Plug data into components with Redux. (Illustration by Beebee) (Large preview)
Note: In the latest version of React (16.3), thereâs a new âcontextâ API that does almost the same job in terms of plugging data into components. So if this is the only reason your team is using Redux, seriously consider upgrading to React 16.3! Check out the official document for more information (warning: lots of code ahead).
Changing Data
Sometimes the logic of updating data in an app can be fairly complex. It might involve multiple steps that depend on one another. We may need to wait for the responses from multiple servers before updating the application state. We might need to update many places in the state at different times under different conditions.
It can be overwhelming if we donât have a good structure for all this logic. The code would be difficult to understand and maintain.
Redux allows us to divide and conquer. It provides a standard way to break data updating logic into small âreducersâ. Those reducers work harmoniously together to complete a complex action.
Divide complex logic into reducers. (Illustration by Beebee) (Large preview)
Keep an eye on the recent development of React, though. As with the âcontextâ API, there might be a new âsetStateâ API in a future version of React. Itâd make it easier to break up complex update logic into smaller parts. Once this new API becomes available, itâs possible that you wonât be needing Redux anymore to manage this aspect of state management.
The Real Power Of Redux
So far, it seems Redux is just a band-aid for React. People use Redux to improve aspects that React doesnât do well (yet). But React is catching up quickly! In fact, Dan Abramov, the creator of Redux, joined the React core team at Facebook a couple of years ago. They have been busy working on the aforementioned improvements to React: context API (released in 16.3), better data fetching API (demoed in Feb 2018), a better setState API and so on.
Will it make Redux obsolete?
Guess what? I havenât shown you the real power of Redux yet!
Redux' power is way beyond state management. (Illustration by Beebee) (Large preview)
Redux forces developers to follow a few strict rules, which bring Redux a lot of power (yup, the power of discipline!):
All the data (application state) has to be described in clear text. You should be able to write down all the data with a pen on paper.
Every action (change of data) has to be described in clear text. You must write down what youâll do before changing anything. You canât change data without leaving a mark. This process is called âdispatching an actionâ in Redux slang.
Your code that changes data must behave like a math formula. It must return the same result given the same input. The square of 4 is always 16 no matter how many times you run it.
When you follow these rules to build apps, magic happens. It enables a lot of cool features that are otherwise difficult or expensive to implement. Here are some examples.2
2 I collected these examples from Dan Abramovâs post âYou Might Not Need Reduxâ and his ïżœïżœReact Beginner Question Thread.â
Undo, Redo
The popular undo/redo feature requires system-level planning. Because undo/redo needs to record and replay every single change of data in the app, you must take it into account in the architecture from the very beginning. If itâs done as an afterthought, itâd require changing a lot of files which is a recipe for countless bugs.
Undo, redo. (Illustration by Beebee) (Large preview)
Because Redux requires every action to be described in clear text, the support for undo/redo almost comes for free. The instructions of how to implement undo/redo with Redux fit in a simple page.
Collaborative Environment
If you are building an app similar to Google Docs where multiple users work together on a complex task, consider using Redux. It will likely do a lot of weightlifting for you.
Google Docs (Illustration by Beebee) (Large preview)
Redux makes it very easy to send what is happening over the network. Itâs straightforward to receive actions another user performs on another machine, replay the changes and merge with whatâs happening locally.
Optimistic UI
Optimistic UI is a way to improve the user experience of an app. It makes the app appear to respond faster over a slow network. Itâs a popular strategy in apps that require real-time responses, for example, a first-person shooter game.
Optimistic UI (Illustration by Beebee) (Large preview)
As a simple example, in the Twitter app, when you click the heart on a tweet, it needs to request the server to do a few checkups, for example, whether that tweet still exists. Instead of waiting many seconds for the result, the app chooses to cheat! It assumes everything is OK and shows a filled heart right away.
Twitter heart (Illustration by Beebee) (Large preview)
This approach works because most of the time everything is OK. When things are not OK, the app will revert the previous UI updates and apply the actual result from the server, for example, show an error message.
Redux supports optimistic UI in the same fashion as what it does for undo and redo. It makes it easy to record, replay and revert changes of data when receiving a negative result from the server.
Persisting And Booting Up From State
Redux makes it easy to save whatâs happening in an app in the storage. Later on, even if the computer restarts, the app can load all the data and continue from exactly the same spot, as if itâs never been interrupted.
Save/load game progress (Illustration by Beebee) (Large preview)
If you build a game with Redux, youâd just need a couple more lines of code to save/load the game progress, without changing the rest of the code.
Really Extensible Systems
With Redux, you must âdispatchâ an action to update any data in an app. This restriction makes it possible to hook into almost every aspect of whatâs happening in an app.
You can build really extensible apps where every function can be customized by the user. For example, check out Hyper, a terminal app built with Redux. The âhyperpowerâ extension adds sprinkles to the cursor and shakes up the window. How do you like this âwowâ mode? (Perhaps not terribly useful but enough to impress users)
The âwowâ mode in Hyper, a terminal app. (Large preview)
Time-Travel Debugging
How about being able to travel in time when debugging an app? You run the app, rewind or forward a few times to find the exact place when the bug occurs, fix the bug and re-play to confirm.
Redux makes this dream of developers come true. Redux DevTools allows you to manipulate the progress of a running app as a YouTube video â by dragging a slider!
How does it work? Remember the three strict rules that Redux enforces? Thatâs the secret sauce of the magic.
Time travel in Redux DevTools Large preview
Automated Bug Reports
Imagine this: A user finds something wrong in your app and wants to report the bug. She painstakingly recalls and describes what she has done. A developer then tries to follow the steps manually to see if the bug occurs again. The bug report may be vague or inaccurate. The developer is having a hard time finding where the bug is.
Now, how about this. The user clicks the âReport bugâ button. The system automatically sends what she has done to the developer. The developer clicks the âReplay bugâ button and watches how that bug exactly happens. The bug is squashed on the spot, everybody is happy!
This is exactly what would happen if you use Redux Bug Reporter. How does it work? The Redux restrictions make wonders.
Automated bug reports (Illustration by Beebee) (Large preview)
Downsides Of Redux
The three major rules that Redux enforces are a double-edged sword. They enable powerful features, but at the same time cause inevitable downsides.
Steep Learning Curve
Redux has a relatively steep learning curve. It takes time to understand, remember and get used to its patterns. Itâs not recommended to learn Redux and React at the same time if they are both new to you.
âBoilerplateâ Code
In many cases, using Redux means writing more code. Itâs often required to touch multiple files to get a simple feature working. People have been complaining about the âboilerplateâ code theyâd have to write with Redux.
I know, this sounds contradictory. Didnât I say Redux makes it possible to implement features with minimal code? This is a bit like using a dishwasher. First, youâd have to spend the time carefully arranging the dishes in rows. Not until then you will see the benefits of the dishwasher: saving time on actually cleaning the dishes, sanitizing the dishes etc. You have to decide whether the preparation time is worth it!
Performance Penalty
Redux could also have an impact on performance due to the restrictions it enforces. It adds a little overhead whenever the data changes. In most cases, itâs not a big deal, and the slowdown is not noticeable. Still, when thereâs a large amount of data in the store and when the data changes frequently (e.g. when the user is typing rapidly on a mobile device), the UI may become sluggish as a result.
Bonus: Redux Is Not Just For React
A common misconception is that Redux is for React only. It sounds like Redux canât do anything without React. Indeed, Redux complements React in a few important ways, as we have discussed earlier. Itâs the most common use case.
However, in fact, Redux can work with any front-end frameworks, such as Angular, Ember.js or even jQuery, or even vanilla JavaScript. Try googling it, youâll find this, this, this or even this. The general ideas of Redux apply anywhere!
As long as you use Redux wisely, you can get its benefits in many situations â not just in a React app.
Redux works well with other front-end libraries. (Illustration by Beebee) (Large preview)
Conclusion
As any tool, Redux offers a tradeoff. It enables powerful features but also has inevitable drawbacks. The job of a development team is to evaluate whether the tradeoff is worth it and make a conscious decision.
As designers, if we understand the advantages and downsides of Redux, weâll be able to contribute to this decision making from the perspective of design. For example, perhaps we could design the UI to mitigate the potential performance impact? Perhaps we could advocate the inclusion of undo/redo features to remove a boatload of confirmation dialogs? Perhaps we could suggest optimistic UI since it improves user experience with a relatively low cost?
Understand the benefits and limitations of a technology, and design accordingly. I think thatâs what Steve Jobs meant by âdesign is how it works.â
(rb, ra, il)
0 notes
Text
What Is Redux: A Designerâs Guide
What Is Redux: A Designerâs Guide
Linton Ye
2018-07-05T15:30:46+02:002018-07-10T12:05:47+00:00
Have you heard of Redux? What is it? No googling, please!
âFancy backend stuff.â
âI have heard of it, but Iâm not aware of what it is. Itâs a React framework perhaps?â
âA better way to store and manage states in a React application.â
Iâve asked this question to over 40 designers. The above are their typical answers. Many of them are aware that Redux works with React and its job is âstate management.â
But do you know what this âstate managementâ really means? Do you know Reduxâs real power is beyond managing the state? Do you know that Redux doesnât necessarily require React to work? Do you want to join your teamâs discussion (or at least lunch chats) about whether to use Redux? Do you want to design with an understanding of how Redux works in mind?
With the help of this article, Iâd like to show you a full picture of Redux: what it can do, why it does its things, what the downsides are, when to use it, and how it relates to design.
My goal is to help designers like you. Even if you havenât written a single line of code before, I think itâs still possible and beneficial (and fun) to understand Redux. Expect plain English and doodles â no code or abstract talks.
Ready for the ride?
With so much happening on the web, what should we really pay attention to? At SmashingConf New York 2018 đșđž weâll explore everything from PWAs, font loading best practices, web performance and eCommerce UX optimization, to refactoring CSS, design workflows and convincing your clients. With Sarah Drasner, Dan Mall, Sara Soueidan, Jason Grigsby, and many other speakers. Oct 23â24.
Check the speakers â
What Is Redux?
At a super-high level, Redux is a tool that developers use to make their lives easier. As many of you might have heard, its job is âstate management.â Iâll explain what state management means a few sections later. At this point, Iâll leave you with this picture:
Redux manages state, but in the background, there are a few hidden powers. (Illustration by Beebee) (Large preview)
Why Should You Care?
Redux is more about the inner workings of an app than its look-and-feel. Itâs a somewhat complex tool with a steep learning curve. Does that mean we, as designers, should stay far away from it?
No. I think we should embrace it. A car designer should understand what the engine is for, right? To successfully design app interfaces, designers should also have solid knowledge about things under the hood. We should learn about what it can do, understand why developers use it, and be aware of its advantages and implications.
âDesign is not just what it looks like and feels like. Design is how it works.â â Steve Jobs
What Can Redux Do?
Many people use Redux to manage the state in React apps. Itâs the most common use case in the wild and Redux improves the aspects where React doesnât do well (yet).
However, youâll soon see that the real power of Redux goes way beyond that. Letâs get started by learning what state management really means.
State Management
If you are not sure what this âstateâ means, letâs replace it with a more generic term: âdata.â State is data that change from time to time. State determines whatâs displayed on the user interface.
What does state management mean? In general, there are three aspects of data that weâd need to manage in an app:
Fetching and storing data
Assigning data to UI elements
Changing data
Letâs say we are building a Dribbble shot page. What is the data we want to display on the page? They include the authorâs profile photo, name, the animated GIF, the number of hearts, the comments, and so on.
Data on a Dribbble shot page (Large preview)
First, we need to fetch all these data from a server in the cloud and put it somewhere. Next, we need to actually display the data. We need to assign pieces of this data to corresponding UI elements that represent what we actually see in the browser. For example, we assign the URL of the profile photo to the src attribute of an HTML img tag:
<img src='https://url/to/profile_photo'>
Finally, we need to handle changes to the data. For example, if a user adds a new comment to a Dribbble shot, or adds a star, we need to update the HTML accordingly.
Coordinating these three aspects of state is a big part in front-end development, and React has various degree of support for this task. Sometimes the built-in facility in React works well enough. But as the app grows more complex, its state may become harder to manage with React alone. Thatâs why many people start using Redux as an alternative.
Fetching And Storing Data
In React, we break down a UI into components. Each of these components can be broken down into smaller components (see âWhat is React?â).
Dribbble shot page broken down into components (Large preview)
If our UI is structured this way, when do we fetch the data and where to store it before populating the UI?
Imagine thereâs a chef living in each component. Fetching data from servers is like sourcing all the ingredients needed to prepare dishes.
A naive way is to fetch and store the data where and when itâs needed. This is like each chef going out to buy vegetables and meats directly from far-away farms.
The naive way: fetch data from each component. (Illustration by Beebee) (Large preview)
This approach is wasteful. Weâd need to call the server many times from many components â even for the same data. The chefs would waste a lot of gas and time traveling back and forth.
With Redux, we fetch data once and store it in a central place, conveniently called âstore.â The data is then ready for use anytime by any component. This is not unlike having a superstore nearby where our chefs can buy all the ingredients. The superstore sends trucks to carry back vegetables and meats in bulk from farms. Itâs a lot more efficient than asking individual chefs to go to the farms themselves!
The store also serves as the single source of truth. Components always retrieve data from the store, not from anywhere else. This keeps all the UI content consistent.
Redux as a central store of data. (Illustration by Beebee) (Large preview)
Assigning Data To UI Elements
With only React, thereâs actually a better way to fetch and store data. We can ask our very kind chef Shotwell to do the shopping for all his chef friends. He would drive a truck to the farms and carry back the goodies. We could fetch data from a container component, for example, the âShotâ component in the Dribbble example, and use that as the single source of truth.
Fetch data from the root component. (Illustration by Beebee) (Large preview)
This approach is more efficient than the naive way of fetching data from every component. But how does Shotwell pass the ingredients to other chefs? How to pass the data to the components that actually render HTML elements? We pass data from outer components to inner components like the baton in a relay, all the way until the data reach the destination.
For example, the URL of the author avatar needs to be passed from âShotâ, to âShotDetailâ, to âTitleâ and finally to the <img> tag. If our chefs live in an apartment, it really looks like this:
Pass data to components via props. (Illustration by Beebee) (Large preview)
To deliver data to the destination, weâd have to engage all the components on the path, even if they donât need the data at all. Itâd be really annoying if there are many floors!
What if the superstore does door-to-door delivery? With Redux1, we can plug in any data into any component, without affecting other components at all, like so:
1 To be absolutely accurate, itâs another library called react-redux that hands data to React components, not Redux itself. But since react-redux just does the plumbing and people almost always use Redux and react-redux together, I think itâs fine to include this as one of the benefits of Redux.
Plug data into components with Redux. (Illustration by Beebee) (Large preview)
Note: In the latest version of React (16.3), thereâs a new âcontextâ API that does almost the same job in terms of plugging data into components. So if this is the only reason your team is using Redux, seriously consider upgrading to React 16.3! Check out the official document for more information (warning: lots of code ahead).
Changing Data
Sometimes the logic of updating data in an app can be fairly complex. It might involve multiple steps that depend on one another. We may need to wait for the responses from multiple servers before updating the application state. We might need to update many places in the state at different times under different conditions.
It can be overwhelming if we donât have a good structure for all this logic. The code would be difficult to understand and maintain.
Redux allows us to divide and conquer. It provides a standard way to break data updating logic into small âreducersâ. Those reducers work harmoniously together to complete a complex action.
Divide complex logic into reducers. (Illustration by Beebee) (Large preview)
Keep an eye on the recent development of React, though. As with the âcontextâ API, there might be a new âsetStateâ API in a future version of React. Itâd make it easier to break up complex update logic into smaller parts. Once this new API becomes available, itâs possible that you wonât be needing Redux anymore to manage this aspect of state management.
The Real Power Of Redux
So far, it seems Redux is just a band-aid for React. People use Redux to improve aspects that React doesnât do well (yet). But React is catching up quickly! In fact, Dan Abramov, the creator of Redux, joined the React core team at Facebook a couple of years ago. They have been busy working on the aforementioned improvements to React: context API (released in 16.3), better data fetching API (demoed in Feb 2018), a better setState API and so on.
Will it make Redux obsolete?
Guess what? I havenât shown you the real power of Redux yet!
Redux' power is way beyond state management. (Illustration by Beebee) (Large preview)
Redux forces developers to follow a few strict rules, which bring Redux a lot of power (yup, the power of discipline!):
All the data (application state) has to be described in clear text. You should be able to write down all the data with a pen on paper.
Every action (change of data) has to be described in clear text. You must write down what youâll do before changing anything. You canât change data without leaving a mark. This process is called âdispatching an actionâ in Redux slang.
Your code that changes data must behave like a math formula. It must return the same result given the same input. The square of 4 is always 16 no matter how many times you run it.
When you follow these rules to build apps, magic happens. It enables a lot of cool features that are otherwise difficult or expensive to implement. Here are some examples.2
2 I collected these examples from Dan Abramovâs post âYou Might Not Need Reduxâ and his âReact Beginner Question Thread.â
Undo, Redo
The popular undo/redo feature requires system-level planning. Because undo/redo needs to record and replay every single change of data in the app, you must take it into account in the architecture from the very beginning. If itâs done as an afterthought, itâd require changing a lot of files which is a recipe for countless bugs.
Undo, redo. (Illustration by Beebee) (Large preview)
Because Redux requires every action to be described in clear text, the support for undo/redo almost comes for free. The instructions of how to implement undo/redo with Redux fit in a simple page.
Collaborative Environment
If you are building an app similar to Google Docs where multiple users work together on a complex task, consider using Redux. It will likely do a lot of weightlifting for you.
Google Docs (Illustration by Beebee) (Large preview)
Redux makes it very easy to send what is happening over the network. Itâs straightforward to receive actions another user performs on another machine, replay the changes and merge with whatâs happening locally.
Optimistic UI
Optimistic UI is a way to improve the user experience of an app. It makes the app appear to respond faster over a slow network. Itâs a popular strategy in apps that require real-time responses, for example, a first-person shooter game.
Optimistic UI (Illustration by Beebee) (Large preview)
As a simple example, in the Twitter app, when you click the heart on a tweet, it needs to request the server to do a few checkups, for example, whether that tweet still exists. Instead of waiting many seconds for the result, the app chooses to cheat! It assumes everything is OK and shows a filled heart right away.
Twitter heart (Illustration by Beebee) (Large preview)
This approach works because most of the time everything is OK. When things are not OK, the app will revert the previous UI updates and apply the actual result from the server, for example, show an error message.
Redux supports optimistic UI in the same fashion as what it does for undo and redo. It makes it easy to record, replay and revert changes of data when receiving a negative result from the server.
Persisting And Booting Up From State
Redux makes it easy to save whatâs happening in an app in the storage. Later on, even if the computer restarts, the app can load all the data and continue from exactly the same spot, as if itâs never been interrupted.
Save/load game progress (Illustration by Beebee) (Large preview)
If you build a game with Redux, youâd just need a couple more lines of code to save/load the game progress, without changing the rest of the code.
Really Extensible Systems
With Redux, you must âdispatchâ an action to update any data in an app. This restriction makes it possible to hook into almost every aspect of whatâs happening in an app.
You can build really extensible apps where every function can be customized by the user. For example, check out Hyper, a terminal app built with Redux. The âhyperpowerâ extension adds sprinkles to the cursor and shakes up the window. How do you like this âwowâ mode? (Perhaps not terribly useful but enough to impress users)
The âwowâ mode in Hyper, a terminal app. (Large preview)
Time-Travel Debugging
How about being able to travel in time when debugging an app? You run the app, rewind or forward a few times to find the exact place when the bug occurs, fix the bug and re-play to confirm.
Redux makes this dream of developers come true. Redux DevTools allows you to manipulate the progress of a running app as a YouTube video â by dragging a slider!
How does it work? Remember the three strict rules that Redux enforces? Thatâs the secret sauce of the magic.
Time travel in Redux DevTools Large preview
Automated Bug Reports
Imagine this: A user finds something wrong in your app and wants to report the bug. She painstakingly recalls and describes what she has done. A developer then tries to follow the steps manually to see if the bug occurs again. The bug report may be vague or inaccurate. The developer is having a hard time finding where the bug is.
Now, how about this. The user clicks the âReport bugâ button. The system automatically sends what she has done to the developer. The developer clicks the âReplay bugâ button and watches how that bug exactly happens. The bug is squashed on the spot, everybody is happy!
This is exactly what would happen if you use Redux Bug Reporter. How does it work? The Redux restrictions make wonders.
Automated bug reports (Illustration by Beebee) (Large preview)
Downsides Of Redux
The three major rules that Redux enforces are a double-edged sword. They enable powerful features, but at the same time cause inevitable downsides.
Steep Learning Curve
Redux has a relatively steep learning curve. It takes time to understand, remember and get used to its patterns. Itâs not recommended to learn Redux and React at the same time if they are both new to you.
âBoilerplateâ Code
In many cases, using Redux means writing more code. Itâs often required to touch multiple files to get a simple feature working. People have been complaining about the âboilerplateâ code theyâd have to write with Redux.
I know, this sounds contradictory. Didnât I say Redux makes it possible to implement features with minimal code? This is a bit like using a dishwasher. First, youâd have to spend the time carefully arranging the dishes in rows. Not until then you will see the benefits of the dishwasher: saving time on actually cleaning the dishes, sanitizing the dishes etc. You have to decide whether the preparation time is worth it!
Performance Penalty
Redux could also have an impact on performance due to the restrictions it enforces. It adds a little overhead whenever the data changes. In most cases, itâs not a big deal, and the slowdown is not noticeable. Still, when thereâs a large amount of data in the store and when the data changes frequently (e.g. when the user is typing rapidly on a mobile device), the UI may become sluggish as a result.
Bonus: Redux Is Not Just For React
A common misconception is that Redux is for React only. It sounds like Redux canât do anything without React. Indeed, Redux complements React in a few important ways, as we have discussed earlier. Itâs the most common use case.
However, in fact, Redux can work with any front-end frameworks, such as Angular, Ember.js or even jQuery, or even vanilla JavaScript. Try googling it, youâll find this, this, this or even this. The general ideas of Redux apply anywhere!
As long as you use Redux wisely, you can get its benefits in many situations â not just in a React app.
Redux works well with other front-end libraries. (Illustration by Beebee) (Large preview)
Conclusion
As any tool, Redux offers a tradeoff. It enables powerful features but also has inevitable drawbacks. The job of a development team is to evaluate whether the tradeoff is worth it and make a conscious decision.
As designers, if we understand the advantages and downsides of Redux, weâll be able to contribute to this decision making from the perspective of design. For example, perhaps we could design the UI to mitigate the potential performance impact? Perhaps we could advocate the inclusion of undo/redo features to remove a boatload of confirmation dialogs? Perhaps we could suggest optimistic UI since it improves user experience with a relatively low cost?
Understand the benefits and limitations of a technology, and design accordingly. I think thatâs what Steve Jobs meant by âdesign is how it works.â
(rb, ra, il)
0 notes
Text
There is no such thing as serverless
In my recent chapter of my quest to learn more about application architectures, I attended a meet-up put on by a company called Serverless. Their product, the Serverless Framework, attempts to abstract all server-related functionality that your application will ever need. Perhaps the term âserverlessâ is misleading here: Your application will still be âservedâ from a server, just not one youâll have to build. No, this is not a fancy blockchain that works without a central server and uses a peer-to-peer network to replicate data across clientsâŠ
The term âServerlessâ, as it is commonly referred to today, (also known as FaaS, Function-As-A-Service) is actually an emerging architectural approach, in which companies try to bring enterprise-quality application server management into their products. This is done by using already existing cloud features/functions instead of building server components in-house. Using such an approach encourages companies to implement solutions which do more work on the server, such as isomorphic UI applications. The servers themselves are better managed by being easy and faster to set-up and refactor. Of course, this comes with a monthly cost; still, companies donât need to purchase, rent, or provision application servers. So it becomes well worth it.
But all of these things I described so far are available on AWS. Why not just go straight to the source? Well, based on a statement by Adam Johnson (CEO and co-founder of IOpipe), the Serverless Framework is really a more powerful interface to AWS. It is helpful for modern Single Page Applications, and is easier âout of the boxâ than going straight to AWS. In any case, the question and answer session was abruptly cut off by the CEO during the meet-up presentations, after only one question was asked. Perhaps this is the kind of question the CEO, who led the meet-up personally, did not want asked out loud? I had to quietly extract this information from Adam Johnson who was standing against the side of the room :)
With an application that is fully integrated into AWS using the Serverless Framework, client requests go through a series of customizable AWS lambda functions. CloudWatch monitoring services are employed to collect, understand, and track metrics for usage, errors, internal invocations, and other things worth logging. A lot of resources are created and managed so that you can utilize your lambda functions. But this can bring its own complexity with it, as well as longer deployments, depending on how your âserverlessâ architecture is set up.
There are also other reasons to use the Serverless Framework. The obvious one is that it makes life easier for Dev Ops engineers. It also allows you to programmatically customize your server needs into separate state machines, security groups, and event streams. You can more easily manage your lambda functions with UI tools which help you define them, and even debug them on-the-fly using breakpoints. It seems to be conducive to requirements of many different types of applications (from large-scale IoT systems to those serving simple HTML pages). Other common uses include: various data storage access implementations, image resizing utilities, event streams for queue throttling, and realtime notifications. Finally, it helps you track the performance and usage of your entire server layer.
So in conclusion, the Serverless Framework seems to be a good solution to help you in the land of cloud-hosted web services that involve a completely abstract, distributed architecture. However, It is not a truly âserver-lessâ solution like the name implies. Youâll have to look into blockchain technologies for that :)
1 note
·
View note
Text
Creating Sortable Tables With React
About The Author
Kristofer is the React lead at Bekk, and has worked on numerous large projects for the last 6 years. He hosts a beer based programming meetup, tries to keep his ⊠More about Kristofer âŠ
Making your tables sortable in React might sound like a daunting task, but it doesnât have to be too difficult. In this article, weâre going to implement all you need to sort out all of your table sorting needs.
Table sorting has always been a pretty hard issue to get right. Thereâs a lot of interactions to keep track of, extensive DOM mutations to do and even intricate sorting algorithms, too. Itâs just one of those challenges that are hard to get right. Right?
Instead of pulling in external libraries, letâs try to make stuff ourselves. In this article, weâre going to create a reusable way to sort your tabular data in React. Weâll go through each step in detail, and learn a bunch of useful techniques along the way.
We wonât go through basic React or JavaScript syntax, but you donât have to be an expert in React to follow along.
Creating A Table With React
First, letâs create a sample table component. Itâll accept an array of products, and output a very basic table, listing out a row per product.
function ProductTable(props) { const { products } = props; return ( <table> <caption>Our products</caption> <thead> <tr> <th>Name</th> <th>Price</th> <th>In Stock</th> </tr> </thead> <tbody> {products.map(product => ( <tr key={product.id}> <td>{product.name}</td> <td>{product.price}</td> <td>{product.stock}</td> </tr> ))} </tbody> </table> ); }
Here, we accept an array of products and loop them out into our table. Itâs static and not sortable at the moment, but thatâs fine for now.
Sorting The Data
If youâd believe all the whiteboard interviewers, youâd think software development was almost all sorting algorithms. Luckily, we wonât be looking into a quick sort or bubble sort here.
Sorting data in JavaScript is pretty straightforward, thanks to the built-in array function sort(). Itâll sort arrays of numbers and strings without an extra argument:
const array = ['mozzarella', 'gouda', 'cheddar']; array.sort(); console.log(array); // ['cheddar', 'gouda', 'mozzarella']
If you want something a bit more clever, you can pass it a sorting function. This function is given two items in the list as arguments, and will place one in front of the other based on what you decide.
Letâs start by sorting the data we get alphabetically by name.
function ProductTable(props) { const { products } = props; let sortedProducts = [...products]; sortedProducts.sort((a, b) => { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; }); return ( <Table> {/* as before */} </Table> ); }
So whatâs going on here? First, we create a copy of the products prop, which we can alter and change as we please. We need to do this because the Array.prototype.sort function alters the original array instead of returning a new sorted copy.
Next, we call sortedProducts.sort, and pass it a sorting function. We check if the name property of the first argument a is before the second argument b, and if so, return a negative value. This indicates that a should come before b in the list. If the first argumentâs name is after the second argumentâs name, we return a positive number, indicating that we should place b before a. If the two are equal (i.e. both have the same name), we return 0 to preserve the order.
Making Our Table Sortable
So now we can make sure the table is sorted by name â but how can we change the sorting order ourselves?
To change what field we sort by, we need to remember the currently sorted field. Weâll do that with the useState hook.
A hook is a special kind of function that lets us âhookâ into some of Reactâs core functionality, like managing state and triggering side effects. This particular hook lets us maintain a piece of internal state in our component, and change it if we want to. This is what weâll add:
const [sortedField, setSortedField] = React.useState(null);
We start by not sorting anything at all. Next, letâs alter the table headings to include a way to change what field we want to sort by.
const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); return ( <table> <thead> <tr> <th> <button type="button" onClick={() => setSortedField('name')}> Name </button> </th> <th> <button type="button" onClick={() => setSortedField('price')}> Price </button> </th> <th> <button type="button" onClick={() => setSortedField('stock')}> In Stock </button> </th> </tr> </thead> {/* As before */} </table> ); };
Now, whenever we click a table heading, we update the field we want to sort by. Neat-o!
Weâre not doing any actual sorting yet though, so letâs fix that. Remember the sorting algorithm from before? Here it is, just slightly altered to work with any of our field names.
const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortedField] < b[sortedField]) { return -1; } if (a[sortedField] > b[sortedField]) { return 1; } return 0; }); } return ( <table>
We first make sure weâve chosen a field to sort by, and if so, we sort the products by that field.
Ascending vs Descending
The next feature we want to see is a way to switch between ascending and descending order. Weâll switch between ascending and descending order by clicking the table heading one more time.
To implement this, weâll need to introduce a second piece of state â the sort order. Weâll refactor our current sortedField state variable to keep both the field name and its direction. Instead of containing a string, this state variable will contain an object with a key (the field name) and a direction. Weâll rename it to sortConfig to be a bit clearer.
Hereâs the new sorting function:
sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; });
Now, if the direction is âascendingâ, weâll do as we did previously. If itâs not, weâll do the opposite, giving us descending ordering.
Next up, weâll create a new function â requestSort â which will accept the field name, and update the state accordingly.
const requestSort = key => { let direction = 'ascending'; if (sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); }
Weâll also have to change our click handlers to use this new function!
return ( <table> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')}> Name </button> </th> <th> <button type="button" onClick={() => requestSort('price')}> Price </button> </th> <th> <button type="button" onClick={() => requestSort('stock')}> In Stock </button> </th> </tr> </thead> {/* as before */} </table> );
Now weâre starting to look pretty feature-complete, but thereâs still one big thing left to do. We need to make sure that we only sort our data when we need to. Currently, weâre sorting all of our data on every render, which will lead to all sorts of performance issues down the line. Instead, letâs use the built-in useMemo hook to memoize all the slow parts!
const ProductsTable = (props) => { const { products } = props; const [sortConfig, setSortConfig] = React.useState(null); React.useMemo(() => { let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortedProducts; }, [products, sortConfig]);
If you havenât seen it before, useMemo is a way to cache â or memoize â expensive computations. So given the same input, it doesnât have to sort the products twice if we re-render our component for some reason. Note that we want to trigger a new sort whenever our products change, or the field or direction we sort by changes.
Wrapping our code in this function will have huge performance implications for our table sorting!
Making It All Reusable
One of the best things about hooks is how easy it is to make logic reusable. Youâll probably be sorting all types of tables throughout your application, and having to reimplement the same stuff all over again sounds like a drag.
React has this feature called custom hooks. They sound fancy, but all they are are regular functions that use other hooks inside of them. Letâs refactor our code to be contained in a custom hook, so we can use it all over the place!
const useSortableData = (items, config = null) => { const [sortConfig, setSortConfig] = React.useState(config); const sortedItems = React.useMemo(() => { let sortableItems = [...items]; if (sortConfig !== null) { sortableItems.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortableItems; }, [items, sortConfig]); const requestSort = key => { let direction = 'ascending'; if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); } return { items, requestSort }; }
This is pretty much copy and paste from our previous code, with a bit of renaming thrown in. useSortableData accepts the items, and an optional initial sort state. It returns an object with the sorted items, and a function to re-sort the items.
Our table code now looks like this:
const ProductsTable = (props) => { const { products } = props; const { items, requestSort } = useSortableData(products); return ( <table>{/* ... */}</table> ); };
A Last Touch
Thereâs one tiny piece missing â a way to indicate how the table is sorted. In order to indicate that in our design, we need to return the internal state as well â the sortConfig. Letâs return that as well, and use it to generate styles we can apply to our table headings!
const ProductTable = (props) => { const { items, requestSort, sortConfig } = useSortableData(props.products); const getClassNamesFor = (name) => { if (!sortConfig) { return; } return sortConfig.key === name ? sortConfig.direction : undefined; }; return ( <table> <caption>Products</caption> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')} className={getClassNamesFor('name')} > Name </button> </th> {/* ⊠*/} </tr> </thead> {/* ⊠*/} </table> ); };
And with that, weâre done!
Wrapping Up
As it turns out, creating your own table sorting algorithm wasnât an impossible feat after all. We found a way to model our state, we wrote a generic sorting function, and we wrote a way to update what our sorting preferences are. We made sure everything was performant and refactored it all into a custom hook. Finally, we provided a way to indicate the sort order to the user.
You can see a demo of the table in this CodeSandbox:
(ra, yk, il)
Website Design & SEO Delray Beach by DBL07.co
Delray Beach SEO
source http://www.scpie.org/creating-sortable-tables-with-react/ source https://scpie1.blogspot.com/2020/03/creating-sortable-tables-with-react.html
0 notes
Text
Creating Sortable Tables With React
About The Author
Kristofer is the React lead at Bekk, and has worked on numerous large projects for the last 6 years. He hosts a beer based programming meetup, tries to keep his ⊠More about Kristofer âŠ
Making your tables sortable in React might sound like a daunting task, but it doesnât have to be too difficult. In this article, weâre going to implement all you need to sort out all of your table sorting needs.
Table sorting has always been a pretty hard issue to get right. Thereâs a lot of interactions to keep track of, extensive DOM mutations to do and even intricate sorting algorithms, too. Itâs just one of those challenges that are hard to get right. Right?
Instead of pulling in external libraries, letâs try to make stuff ourselves. In this article, weâre going to create a reusable way to sort your tabular data in React. Weâll go through each step in detail, and learn a bunch of useful techniques along the way.
We wonât go through basic React or JavaScript syntax, but you donât have to be an expert in React to follow along.
Creating A Table With React
First, letâs create a sample table component. Itâll accept an array of products, and output a very basic table, listing out a row per product.
function ProductTable(props) { const { products } = props; return ( <table> <caption>Our products</caption> <thead> <tr> <th>Name</th> <th>Price</th> <th>In Stock</th> </tr> </thead> <tbody> {products.map(product => ( <tr key={product.id}> <td>{product.name}</td> <td>{product.price}</td> <td>{product.stock}</td> </tr> ))} </tbody> </table> ); }
Here, we accept an array of products and loop them out into our table. Itâs static and not sortable at the moment, but thatâs fine for now.
Sorting The Data
If youâd believe all the whiteboard interviewers, youâd think software development was almost all sorting algorithms. Luckily, we wonât be looking into a quick sort or bubble sort here.
Sorting data in JavaScript is pretty straightforward, thanks to the built-in array function sort(). Itâll sort arrays of numbers and strings without an extra argument:
const array = ['mozzarella', 'gouda', 'cheddar']; array.sort(); console.log(array); // ['cheddar', 'gouda', 'mozzarella']
If you want something a bit more clever, you can pass it a sorting function. This function is given two items in the list as arguments, and will place one in front of the other based on what you decide.
Letâs start by sorting the data we get alphabetically by name.
function ProductTable(props) { const { products } = props; let sortedProducts = [...products]; sortedProducts.sort((a, b) => { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; }); return ( <Table> {/* as before */} </Table> ); }
So whatâs going on here? First, we create a copy of the products prop, which we can alter and change as we please. We need to do this because the Array.prototype.sort function alters the original array instead of returning a new sorted copy.
Next, we call sortedProducts.sort, and pass it a sorting function. We check if the name property of the first argument a is before the second argument b, and if so, return a negative value. This indicates that a should come before b in the list. If the first argumentâs name is after the second argumentâs name, we return a positive number, indicating that we should place b before a. If the two are equal (i.e. both have the same name), we return 0 to preserve the order.
Making Our Table Sortable
So now we can make sure the table is sorted by name â but how can we change the sorting order ourselves?
To change what field we sort by, we need to remember the currently sorted field. Weâll do that with the useState hook.
A hook is a special kind of function that lets us âhookâ into some of Reactâs core functionality, like managing state and triggering side effects. This particular hook lets us maintain a piece of internal state in our component, and change it if we want to. This is what weâll add:
const [sortedField, setSortedField] = React.useState(null);
We start by not sorting anything at all. Next, letâs alter the table headings to include a way to change what field we want to sort by.
const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); return ( <table> <thead> <tr> <th> <button type="button" onClick={() => setSortedField('name')}> Name </button> </th> <th> <button type="button" onClick={() => setSortedField('price')}> Price </button> </th> <th> <button type="button" onClick={() => setSortedField('stock')}> In Stock </button> </th> </tr> </thead> {/* As before */} </table> ); };
Now, whenever we click a table heading, we update the field we want to sort by. Neat-o!
Weâre not doing any actual sorting yet though, so letâs fix that. Remember the sorting algorithm from before? Here it is, just slightly altered to work with any of our field names.
const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortedField] < b[sortedField]) { return -1; } if (a[sortedField] > b[sortedField]) { return 1; } return 0; }); } return ( <table>
We first make sure weâve chosen a field to sort by, and if so, we sort the products by that field.
Ascending vs Descending
The next feature we want to see is a way to switch between ascending and descending order. Weâll switch between ascending and descending order by clicking the table heading one more time.
To implement this, weâll need to introduce a second piece of state â the sort order. Weâll refactor our current sortedField state variable to keep both the field name and its direction. Instead of containing a string, this state variable will contain an object with a key (the field name) and a direction. Weâll rename it to sortConfig to be a bit clearer.
Hereâs the new sorting function:
sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; });
Now, if the direction is âascendingâ, weâll do as we did previously. If itâs not, weâll do the opposite, giving us descending ordering.
Next up, weâll create a new function â requestSort â which will accept the field name, and update the state accordingly.
const requestSort = key => { let direction = 'ascending'; if (sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); }
Weâll also have to change our click handlers to use this new function!
return ( <table> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')}> Name </button> </th> <th> <button type="button" onClick={() => requestSort('price')}> Price </button> </th> <th> <button type="button" onClick={() => requestSort('stock')}> In Stock </button> </th> </tr> </thead> {/* as before */} </table> );
Now weâre starting to look pretty feature-complete, but thereâs still one big thing left to do. We need to make sure that we only sort our data when we need to. Currently, weâre sorting all of our data on every render, which will lead to all sorts of performance issues down the line. Instead, letâs use the built-in useMemo hook to memoize all the slow parts!
const ProductsTable = (props) => { const { products } = props; const [sortConfig, setSortConfig] = React.useState(null); React.useMemo(() => { let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortedProducts; }, [products, sortConfig]);
If you havenât seen it before, useMemo is a way to cache â or memoize â expensive computations. So given the same input, it doesnât have to sort the products twice if we re-render our component for some reason. Note that we want to trigger a new sort whenever our products change, or the field or direction we sort by changes.
Wrapping our code in this function will have huge performance implications for our table sorting!
Making It All Reusable
One of the best things about hooks is how easy it is to make logic reusable. Youâll probably be sorting all types of tables throughout your application, and having to reimplement the same stuff all over again sounds like a drag.
React has this feature called custom hooks. They sound fancy, but all they are are regular functions that use other hooks inside of them. Letâs refactor our code to be contained in a custom hook, so we can use it all over the place!
const useSortableData = (items, config = null) => { const [sortConfig, setSortConfig] = React.useState(config); const sortedItems = React.useMemo(() => { let sortableItems = [...items]; if (sortConfig !== null) { sortableItems.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortableItems; }, [items, sortConfig]); const requestSort = key => { let direction = 'ascending'; if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); } return { items, requestSort }; }
This is pretty much copy and paste from our previous code, with a bit of renaming thrown in. useSortableData accepts the items, and an optional initial sort state. It returns an object with the sorted items, and a function to re-sort the items.
Our table code now looks like this:
const ProductsTable = (props) => { const { products } = props; const { items, requestSort } = useSortableData(products); return ( <table>{/* ... */}</table> ); };
A Last Touch
Thereâs one tiny piece missing â a way to indicate how the table is sorted. In order to indicate that in our design, we need to return the internal state as well â the sortConfig. Letâs return that as well, and use it to generate styles we can apply to our table headings!
const ProductTable = (props) => { const { items, requestSort, sortConfig } = useSortableData(props.products); const getClassNamesFor = (name) => { if (!sortConfig) { return; } return sortConfig.key === name ? sortConfig.direction : undefined; }; return ( <table> <caption>Products</caption> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')} className={getClassNamesFor('name')} > Name </button> </th> {/* ⊠*/} </tr> </thead> {/* ⊠*/} </table> ); };
And with that, weâre done!
Wrapping Up
As it turns out, creating your own table sorting algorithm wasnât an impossible feat after all. We found a way to model our state, we wrote a generic sorting function, and we wrote a way to update what our sorting preferences are. We made sure everything was performant and refactored it all into a custom hook. Finally, we provided a way to indicate the sort order to the user.
You can see a demo of the table in this CodeSandbox:
(ra, yk, il)
Website Design & SEO Delray Beach by DBL07.co
Delray Beach SEO
source http://www.scpie.org/creating-sortable-tables-with-react/ source https://scpie.tumblr.com/post/613138174677549056
0 notes
Text
Creating Sortable Tables With React
About The Author
Kristofer is the React lead at Bekk, and has worked on numerous large projects for the last 6 years. He hosts a beer based programming meetup, tries to keep his ⊠More about Kristofer âŠ
Making your tables sortable in React might sound like a daunting task, but it doesnât have to be too difficult. In this article, weâre going to implement all you need to sort out all of your table sorting needs.
Table sorting has always been a pretty hard issue to get right. Thereâs a lot of interactions to keep track of, extensive DOM mutations to do and even intricate sorting algorithms, too. Itâs just one of those challenges that are hard to get right. Right?
Instead of pulling in external libraries, letâs try to make stuff ourselves. In this article, weâre going to create a reusable way to sort your tabular data in React. Weâll go through each step in detail, and learn a bunch of useful techniques along the way.
We wonât go through basic React or JavaScript syntax, but you donât have to be an expert in React to follow along.
Creating A Table With React
First, letâs create a sample table component. Itâll accept an array of products, and output a very basic table, listing out a row per product.
function ProductTable(props) { const { products } = props; return ( <table> <caption>Our products</caption> <thead> <tr> <th>Name</th> <th>Price</th> <th>In Stock</th> </tr> </thead> <tbody> {products.map(product => ( <tr key={product.id}> <td>{product.name}</td> <td>{product.price}</td> <td>{product.stock}</td> </tr> ))} </tbody> </table> ); }
Here, we accept an array of products and loop them out into our table. Itâs static and not sortable at the moment, but thatâs fine for now.
Sorting The Data
If youâd believe all the whiteboard interviewers, youâd think software development was almost all sorting algorithms. Luckily, we wonât be looking into a quick sort or bubble sort here.
Sorting data in JavaScript is pretty straightforward, thanks to the built-in array function sort(). Itâll sort arrays of numbers and strings without an extra argument:
const array = ['mozzarella', 'gouda', 'cheddar']; array.sort(); console.log(array); // ['cheddar', 'gouda', 'mozzarella']
If you want something a bit more clever, you can pass it a sorting function. This function is given two items in the list as arguments, and will place one in front of the other based on what you decide.
Letâs start by sorting the data we get alphabetically by name.
function ProductTable(props) { const { products } = props; let sortedProducts = [...products]; sortedProducts.sort((a, b) => { if (a.name < b.name) { return -1; } if (a.name > b.name) { return 1; } return 0; }); return ( <Table> {/* as before */} </Table> ); }
So whatâs going on here? First, we create a copy of the products prop, which we can alter and change as we please. We need to do this because the Array.prototype.sort function alters the original array instead of returning a new sorted copy.
Next, we call sortedProducts.sort, and pass it a sorting function. We check if the name property of the first argument a is before the second argument b, and if so, return a negative value. This indicates that a should come before b in the list. If the first argumentâs name is after the second argumentâs name, we return a positive number, indicating that we should place b before a. If the two are equal (i.e. both have the same name), we return 0 to preserve the order.
Making Our Table Sortable
So now we can make sure the table is sorted by name â but how can we change the sorting order ourselves?
To change what field we sort by, we need to remember the currently sorted field. Weâll do that with the useState hook.
A hook is a special kind of function that lets us âhookâ into some of Reactâs core functionality, like managing state and triggering side effects. This particular hook lets us maintain a piece of internal state in our component, and change it if we want to. This is what weâll add:
const [sortedField, setSortedField] = React.useState(null);
We start by not sorting anything at all. Next, letâs alter the table headings to include a way to change what field we want to sort by.
const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); return ( <table> <thead> <tr> <th> <button type="button" onClick={() => setSortedField('name')}> Name </button> </th> <th> <button type="button" onClick={() => setSortedField('price')}> Price </button> </th> <th> <button type="button" onClick={() => setSortedField('stock')}> In Stock </button> </th> </tr> </thead> {/* As before */} </table> ); };
Now, whenever we click a table heading, we update the field we want to sort by. Neat-o!
Weâre not doing any actual sorting yet though, so letâs fix that. Remember the sorting algorithm from before? Here it is, just slightly altered to work with any of our field names.
const ProductsTable = (props) => { const { products } = props; const [sortedField, setSortedField] = React.useState(null); let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortedField] < b[sortedField]) { return -1; } if (a[sortedField] > b[sortedField]) { return 1; } return 0; }); } return ( <table>
We first make sure weâve chosen a field to sort by, and if so, we sort the products by that field.
Ascending vs Descending
The next feature we want to see is a way to switch between ascending and descending order. Weâll switch between ascending and descending order by clicking the table heading one more time.
To implement this, weâll need to introduce a second piece of state â the sort order. Weâll refactor our current sortedField state variable to keep both the field name and its direction. Instead of containing a string, this state variable will contain an object with a key (the field name) and a direction. Weâll rename it to sortConfig to be a bit clearer.
Hereâs the new sorting function:
sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; });
Now, if the direction is âascendingâ, weâll do as we did previously. If itâs not, weâll do the opposite, giving us descending ordering.
Next up, weâll create a new function â requestSort â which will accept the field name, and update the state accordingly.
const requestSort = key => { let direction = 'ascending'; if (sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); }
Weâll also have to change our click handlers to use this new function!
return ( <table> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')}> Name </button> </th> <th> <button type="button" onClick={() => requestSort('price')}> Price </button> </th> <th> <button type="button" onClick={() => requestSort('stock')}> In Stock </button> </th> </tr> </thead> {/* as before */} </table> );
Now weâre starting to look pretty feature-complete, but thereâs still one big thing left to do. We need to make sure that we only sort our data when we need to. Currently, weâre sorting all of our data on every render, which will lead to all sorts of performance issues down the line. Instead, letâs use the built-in useMemo hook to memoize all the slow parts!
const ProductsTable = (props) => { const { products } = props; const [sortConfig, setSortConfig] = React.useState(null); React.useMemo(() => { let sortedProducts = [...products]; if (sortedField !== null) { sortedProducts.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortedProducts; }, [products, sortConfig]);
If you havenât seen it before, useMemo is a way to cache â or memoize â expensive computations. So given the same input, it doesnât have to sort the products twice if we re-render our component for some reason. Note that we want to trigger a new sort whenever our products change, or the field or direction we sort by changes.
Wrapping our code in this function will have huge performance implications for our table sorting!
Making It All Reusable
One of the best things about hooks is how easy it is to make logic reusable. Youâll probably be sorting all types of tables throughout your application, and having to reimplement the same stuff all over again sounds like a drag.
React has this feature called custom hooks. They sound fancy, but all they are are regular functions that use other hooks inside of them. Letâs refactor our code to be contained in a custom hook, so we can use it all over the place!
const useSortableData = (items, config = null) => { const [sortConfig, setSortConfig] = React.useState(config); const sortedItems = React.useMemo(() => { let sortableItems = [...items]; if (sortConfig !== null) { sortableItems.sort((a, b) => { if (a[sortConfig.key] < b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? -1 : 1; } if (a[sortConfig.key] > b[sortConfig.key]) { return sortConfig.direction === 'ascending' ? 1 : -1; } return 0; }); } return sortableItems; }, [items, sortConfig]); const requestSort = key => { let direction = 'ascending'; if (sortConfig && sortConfig.key === key && sortConfig.direction === 'ascending') { direction = 'descending'; } setSortConfig({ key, direction }); } return { items, requestSort }; }
This is pretty much copy and paste from our previous code, with a bit of renaming thrown in. useSortableData accepts the items, and an optional initial sort state. It returns an object with the sorted items, and a function to re-sort the items.
Our table code now looks like this:
const ProductsTable = (props) => { const { products } = props; const { items, requestSort } = useSortableData(products); return ( <table>{/* ... */}</table> ); };
A Last Touch
Thereâs one tiny piece missing â a way to indicate how the table is sorted. In order to indicate that in our design, we need to return the internal state as well â the sortConfig. Letâs return that as well, and use it to generate styles we can apply to our table headings!
const ProductTable = (props) => { const { items, requestSort, sortConfig } = useSortableData(props.products); const getClassNamesFor = (name) => { if (!sortConfig) { return; } return sortConfig.key === name ? sortConfig.direction : undefined; }; return ( <table> <caption>Products</caption> <thead> <tr> <th> <button type="button" onClick={() => requestSort('name')} className={getClassNamesFor('name')} > Name </button> </th> {/* ⊠*/} </tr> </thead> {/* ⊠*/} </table> ); };
And with that, weâre done!
Wrapping Up
As it turns out, creating your own table sorting algorithm wasnât an impossible feat after all. We found a way to model our state, we wrote a generic sorting function, and we wrote a way to update what our sorting preferences are. We made sure everything was performant and refactored it all into a custom hook. Finally, we provided a way to indicate the sort order to the user.
You can see a demo of the table in this CodeSandbox:
(ra, yk, il)
Website Design & SEO Delray Beach by DBL07.co
Delray Beach SEO
source http://www.scpie.org/creating-sortable-tables-with-react/
0 notes
Text
Creating Sortable Tables With React
Sorting the table has always been a rather difficult problem to get right. To keep track of, detailed DOM mutations to do and even complex sorting algorithms, there are a lot of interactions. It is only one of those obstacles which is difficult to get correct. Exactly right?
Instead of pulling out into external libraries, let's try making things ourselves. We will be building a reusable way to sort your tabular data in React in this post. We will go through every move in detail, and learn along the way a bunch of useful techniques.
We're not going to go through basic React or JavaScript syntax, but to follow along, you don't have to be an expert in reacting.
Creating A Table With React
Sorting The Data If you would believe all the interviewers on the whiteboard, you would think that software engineering has been almost all sorting algorithms. Fortunately, we're not going to look into a short type or type of bubble here.
Data sorting in JavaScript is quite straightforward, thanks to the sort) (function of the built-in array. Without an extra argument it will sort arrays of numbers and strings:
const array = ['mozzarella', 'gouda', 'cheddar']; array.sort(); console.log(array); // ['cheddar', 'gouda', 'mozzarella']
If you want something a bit cleverer, a sorting function may be passed. This function is given as arguments to two things in the list, and positions one in front of the other based on what you decide. Let's start by sorting out the data by name which we get alphabetically.
What's happening here, then? First, we create a copy of the prop products, which we can change and modify as we please. We need to do so because the method Array.prototype.sort replaces the original list, rather than returning a new sorted copy. Making Our Table SortableSo now we can make sure that the table is sorted by name, but how can we alter the sorting order ourselves?
We need to recall the field currently sorted to adjust by which field we sort by. We are going to do that with the useState fork.
A hook is a special form of feature that enables one to "hook" into some of the key features of React, such as state control and triggering side effects. This specific hook allows us to retain, and alter, a piece of internal state in our component if we like. That is what we will be adding:
const [sortedField, setSortedField] = React.useState(null);
We start by doing no sorting at all. Next, let's modify the table headings to include a way of changing by which field we want to sort.
Now, whenever we click the heading of a table, we update the field we want to sort by. Neat-o-o! However, we are still not doing any real sorting, so let's resolve that. Mind the algorithm of previous sorting? Here it is, altered only slightly to fit with some of our field names.
Ascending Vs DescendingThe next feature we would like to see is a way to switch from ascending to descending order. By clicking the table heading one more time, we will switch between ascending and descending order. We'll need to add a second piece of state to execute this â the sort order. To retain both the name of the field and its direction we must refactor our current sortedField state variable. This state variable will contain an object with a key (the field name) and a path, rather than a string. To be a little simpler we will rename it to sortConfig.
Now, if the course is 'ascending' we're going to do as we have done before. If it is not, we are going to do the reverse, giving us a downward direction. Next we will create a new function â requestSort â that will accept the name of the field, and update the state accordingly.
Now we are starting to look pretty feature-complete, but one big thing still remains to be done. We need to ensure we sort our data only when we need it. We are currently sorting out all our data on every render, which will lead to all kinds of performance problems down the line. Let's use the built in Memo hook instead to memorize all the slow bits!
If you haven't seen it before, useMemo is a way to archive costly computations â or memoize them. So given the same data, if we re-render our component for some purpose it doesn't have to sort the products twice. Notice that if our goods change we want to cause a new type, or the field or path we sort by changes. Wrapping our code in this feature will have major consequences for the efficiency of our table sorting! Making It All ReusableOne of the best things about hooks is how simple it is to make reusable reasoning. You 're likely to be juggling all types of tables in your submission, and having to re-implement the same stuff sounds like a drag again. React has the functionality called custom hooks. They sound fancy but they're all standard features that use other hooks inside. Let's refactor our code to include in a custom switch, so that we can use it anywhere!
This is pretty much copy and paste from our previous code, with a bit of renaming thrown in. useSortableData accepts the items, and an optional initial sort state. It returns an object with the sorted items, and a function to re-sort the items.Our table code now looks like this:
A Last Touch
Wrapping UpAs it turns out, after all, building your own table sorting algorithm was not an unthinkable task. We found a way to model our state, we wrote a generic sorting function and we wrote a way of updating what our preferences for sorting are. We ensured everything was performing and refactured everything into a custom hook. Finally, we've provided the user with a way to show the sort order.
As a reputed Software Solutions Developer we have expertise in providing dedicated remote and outsourced technical resources for software services at very nominal cost. Besides experts in full stacks We also build web solutions, mobile apps and work on system integration, performance enhancement, cloud migrations and big data analytics. Donât hesitate to
get in touch with us!
Source:
whizzystack.co
#b2b content marketing
#b2b ecommerce
#Ecommerce
#socialmediamarketing
#web development
0 notes
Text
Vue.js Tutorial: A Prerendered, SEO-Friendly Example [Live Demonstration]
"I can't take it anymore; our in-house reporting panel SUCKS."
Our product manager was pissed off. The crumbling app he was trying to pull data from was... disastrous.
"Max, we need better reporting. Can you fix it?"
"Honestly, I'd much rather build a brand new app," I answered, grinning.
"Sure, go ahead. Carte blanche, buddy."
I rubbed my hands, grinning still. FINALLY, an occasion to use the JS framework everyone's been raving about: Vue.js.
I've just finished coding that app, and I loved it.
Inspired by my recent experience, I took some time to craft a Vue.js tutorial for our community. Now, I'll be covering mostly two topics in here:
How to build a lean web app with Vue.js
How to handle Vue.js SEO & prerendering with
More specifically, I'll walk you through creating a small shop with SEO-friendly product pages. A live demo & code repo will also be available. If you're looking for more in-depth knowledge on SEO with a Vue.js SPA we also crafted a video tutorial that you'll find at the end of this post.
 Post update: We're progressively migrating Snipcart's front-end from Backbone to Vue.js, you can read about it right here. Vue transformations are also covered here, and building a blog with Vue here.
Let's start by dropping a little knowledge for those not familiar with the progressive framework.
What is Vue.js exactly?
Vue is a lightweight, progressive JavaScript framework that helps you create web interfaces.
Don't be fooled by the "JS framework" part of the definition just yet. For Vue is quite different from its trendy counterpartsâReact.js & Angular.js. For starters, it's not an open source by-product of commercial tech giants like Google & Facebook.
Evan You first released it in 2014, with the intention of creating an "incrementally adoptable," modern JS library. That's one of the most powerful features of Vue: creating pluggable components you can add to any project without undergoing major refactors. Any developer can try out Vue in a project without jeopardizing or burdening its existing code base.
Pattern terminology apart, I feel like the premises of Vue are:
1. You can't know the entire state architecture of your app from the start
2. Your data will surely change on the runtime
It's around these constraints that the library shapes itself: it's incremental, component-based, and reactive. The granular architecture of the components lets you easily separate your logic concerns while maintaining reusability for them. On top of that, it natively binds your data to the views so they magically update when necessary (through watchers). Although the same definition could be said of many reactive frontend frameworks, I found Vue just achieved it more elegantly, and, for the majority of my use cases, in a better way.
Vue has a softer learning curve than, say, React, which requires JSX templating knowledge.
One could even say Vue is React minus the awkward parts! ;)
For more in-depth comparisons with other JS frameworksâReact, Angular, Ember, Knockout, Polymer, Riotâcheck out the official docs on the subject.
Last but not least, the performance & insightful dev tools Vue offers make for a great coding experience. No wonder its adoption is skyrocketing.
From open source projects like Laravel & PageKit to enterprise ones like Gitlab & Codeship (not to mention the Alibaba & Baidu giants), lots of organizations are using Vue.
Now, however, it's time to see how we are going to use it.
Our Vue.js example: a quick, SEO-friendly e-commerce app
In this section, I'll show you how to build a small e-commerce app using Vue 2.0 & Snipcart, our HTML/JS cart platform for devs. We'll also see how to make sure product pages are properly "crawlable" for search engine bots.
Pre-requisites
If you want to dive deeper into all things Vue 2.0, Laracasts' got you covered with this series.
1. Setting up the environment
First, we'll use the vue-cli to scaffold a basic Vue app. In your favorite terminal, input:
npm install -g vue-cli vue init webpack-simple vue-snipcart
This will create a new vue-snipcart folder containing a basic configuration using vue-loader. It will also enable us to write a single file component (template/js/css in the same .vue file).
We want this demo to feel as real as possible, so we'll add two more modules widely used in Vue SPA for large applications: vuex and vue-router.
vuex is a flux-like state managerâreally light yet very powerful. It's strongly influenced by Redux, on which you can learn more here.
vue-router lets you define routes to dynamically handle components of your app.
To install these, go in your new vue-snipcart project folder and run the following commands:
npm install --save vue-router npm install --save vuex
Another thing to install now is the prerender-spa-plugin, which will enable us to prerender crawlable routes:
npm install --save prerender-spa-plugin
We're almost there, the last four packages are:
pugâfor templates, I prefer that to HTML.
vuex-router-syncâto inject some of our router information directly in our vuex state.
copy-webpack-pluginâto make it easier for us to include our static files in the dist folder.
babel-polyfillâto run Vue inside PhantomJS (used by our prerender plugin).
npm install --save pug npm install --save vuex-router-sync npm install --save copy-webpack-plugin npm install --save babel-polyfill
2. Assembling the architecture
Installs: check. Time to set everything so it can handle our store's data.
Let's start with our vuex store. We'll use this to store/access our products info.
For this demo, we'll use static data, although this would still work if we were to fetch it instead.
2.1 Building the store
Create a store folder in the src one, along with 3 files:
state.js to define our static products
getters.js to define a get function to retrieve products by ID
index.js to bundle the first two together
//state.js export const state = { products: [ { id: 1, name: 'The Square Pair', price: 100.00, description: 'Bold & solid.', image: 'https://snipcart.com/media/10171/glasses1.jpeg' }, { id: 2, name: 'The Hip Pair', price: 110.00, description: 'Stylish & fancy.', image: 'https://snipcart.com/media/10172/glasses2.jpeg' }, { id: 3, name: 'The Science Pair', price: 30, description: 'Discreet & lightweight.', image: 'https://snipcart.com/media/10173/glasses3.jpeg' } ] } //getters.js export const getters = { getProductById: (state, getters) => (id) => { return state.products.find(product => product.id == id) } } //index.js import Vue from 'vue' import Vuex from 'vuex' import { state } from './state.js' import { getters } from './getters.js' Vue.use(Vuex) export default new Vuex.Store({ state, getters })
2.2 Building the router
We'll keep our store basic: a homepage listing products + a details page for each product. We'll need to register two routes in our router to handle these:
import VueRouter from 'vue-router' import Vue from 'vue' import ProductDetails from './../components/productdetails.vue' import Home from './../components/home.vue' Vue.use(VueRouter) export default new VueRouter({ mode: 'history', routes: [ { path: '/products/:id', component: ProductDetails }, { path: '/', component: Home }, ] })
We haven't created these components yet, but no worries, they're coming later. ;)
Note that we employed mode: 'history' in our VueRouter declaration. This is important, as our prerender plugin won't work otherwise. The difference is that the router will use the history API instead of hashbangs to navigate.
2.3 Linking everything together
Now that we have both our store and our router, we'll need to register them in our app. Hop in your src/main.js file and update it as follows:
import Vue from 'vue' import App from './App.vue' import router from './router' import { sync } from 'vuex-router-sync' import store from './store' sync(store, router) new Vue({ store, router, render: h => h(App) }).$mount('#app')
Quite simple, right? As mentioned earlier, the sync method from the vuex-router-sync package injects some of the current route information in our store state. We'll use this later on.
3. Crafting the Vue components
Having data feels awesome, but showing it is even better. We'll use three components to achieve that:
Home to show a products listing
Product to be used for each product by our Home component
ProductDetails for our individual product pages
Each of them will be in the src/components folder.
//Home.vue div(class="products") div(v-for="product in products", class="product") product(:product="product") import Product from './../components/Product.vue' export default { name: 'home', components: { Product }, computed: { products(){ return this.$store.state.products } } }
Above, we use the store state to get our products and iterate on them to render a product component for each one.
//Product.vue div(class="product") router-link(v-bind:to="url").product img(v-bind:src="product.image" v-bind:alt="product.name" class="thumbnail" height="200") p {{ product.name }} button(class="snipcart-add-item" v-bind:data-item-name="product.name" v-bind:data-item-id="product.id" v-bind:data-item-image="product.image" data-item-url="/" v-bind:data-item-price="product.price") | Buy it for {{ product.price }}$ export default { name: 'Product', props: ['product'], computed: { url(){ return `/products/${this.product.id}` } } }
We link to each page, handled by our router, which brings us to our last component.
//ProductDetails.vue div(class="product-details") img(v-bind:src="product.image" v-bind:alt="product.name" class="thumbnail" height="200") div(class="product-description" v-bind:href="url") p {{ product.name }} p {{ product. description}} button(class="snipcart-add-item" v-bind:data-item-name="product.name" v-bind:data-item-id="product.id" v-bind:data-item-image="product.image" data-item-url="/" v-bind:data-item-price="product.price") | Buy it for {{ product.price }}$ export default { name: 'ProductDetails', computed: { id(){ return this.$store.state.route.params.id }, product(){ return this.$store.getters.getProductById(this.id) } } }
This one has a little more logic than the others. We get the current ID from the route and then get the associated product from the getter we previously created.
4. Creating the app
Let's use our new components, yeah?
Open the App.vue file. Content in there is still the default one generated from the vue init webpack-simple scaffolding.
Swap everything to this instead:
div(id="app") TopContext router-view import TopContext from './components/TopContext.vue' export default { name: 'app', components: { TopContext } }
The TopContext component isn't really important; it acts only as a header. The key part is the router-view one: it will be determined dynamically by VueRouter, and the associated component we defined earlier will be injected instead.
The last view to update is the index.html. For our use case, we'll create a new static folder in the src one. There, we'll move our index file, and update as follows:
vue-snipcart
You can see we added Snipcart's necessary scripts in the default view. A small component granularly including them could have been cleaner, but since all our views need them, we did it this way.
5. Handling Vue.js SEO with the Prerender plugin
Everything in our app is rendered dynamically with JS, which isn't super for SEO: the asynchronous content of our pages can't be optimally crawled by search engine bots. It wouldn't be smart for us to have an e-commerce website missing out on all that organic traffic opportunity!
Let's use prerendering to bring more SEO opportunities to our Vue.js app. (You can also watch me doing it live in the video tutorial below!)
Compared to Vue SSR (Server-Side Rendering), prerendering is much easier to set up. And quite frankly, the former is , unless you're dealing with lots of routes. Plus, both achieve quite similar results on an SEO level.
Prerendering will allow us to keep our frontend as a fast, light static site that's easily crawlable.
Let's see how we can use it. Go to your webpack file and add the following declaration to your top level export:
plugins: [ new CopyWebpackPlugin([{ from: 'src/static' }]), new PrerenderSpaPlugin( path.join(__dirname, 'dist'), [ '/', '/products/1', '/products/2', '/products/3'] ) ]
Okay, so how does this work?
The CopyWebpackPlugin will copy our static folder (only containing the view referencing our Vue App) to our dist folder. Then, the PrerenderSpaPlugin will use PhantomJS to load the content of our pages and use the results as our static assets.
And voilĂ ! We've now got prerendered, SEO-friendly product pages for our Vue app.
You can test it yourself with the following command:
npm run build
This will generate a dist folder containing everything needed for production.
Other important SEO considerations
Consider adding appropriate meta tags & a sitemap for your app pages. You can learn more about meta tags in the "postProcessHtml" function here.
Great content plays a huge role in modern SEO. We'd advise making sure content on your app is easy to create, edit, and optimize. To empower content editors, consider throwing a headless CMS into the mix and building a true JAMstack.
An HTTPS connexion is now officially a ranking factor for Google. We're hosting this demo on Netlify, which provides free SSL certificates with all plans.
GitHub repo, live Vue demo & video tutorial
Go ahead, check out the demo & code repo for this tuts!
Conclusion
Since I had worked with Vue before, crafting this tutorial went rather smoothly. I must've spent an hour on the demo. I struggled a bit to get CopyWebpackPlugin to work, but eventually found answers in their docs.
I hope this post encourages developers to start using Vue in some projects. Like I said, you can start slowly, by developing a tiny part of an existing project with it. I think it's definitely worth a try. Our lead developer is coding our latest merchant dashboard feature with Vue as I'm writing this, and he loves it. Plus, when set up right, a Vue app can drive good SEO results.
If you feel like getting inspired first, check out the Vue.js Awesome list, which curates loads of Vue examples & projects.
You can also take a look at our tutorial using the kick-ass Vue.js framework Nuxt.js.
PS: We'll try to get Evan You to use Snipcart for the Vue swag, but no promise. We know Threadless is kind of awesome for t-shirts. :)
If you found this post valuable, take a second to share it on Twitter. Found something we missed? Got thoughts on Vue, other frameworks, or handling SEO with them? Comments are all yours!
Source
https://snipcart.com/blog/vuejs-tutorial-seo-example
0 notes