#still need to refactor it and make it /fancy/
Explore tagged Tumblr posts
iobartach · 2 months ago
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!
9 notes · View notes
roll20 · 5 years ago
Text
A New Light
Tumblr media
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.
Tumblr media
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
illwork4anime · 4 years ago
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
tomswifty-fr · 4 years ago
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
neverheardnothing · 5 years ago
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).
16 notes · View notes
secretcupcakesublime · 4 years ago
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!
0 notes
technicallyelegantruins · 4 years ago
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
captainsafia · 7 years ago
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
dorothydelgadillo · 6 years ago
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:
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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:
Tumblr media
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.
Tumblr media
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.
Tumblr media
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!
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.”
Tumblr media
(rb, ra, il)
0 notes
nancydsmithus · 6 years ago
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:
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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:
Tumblr media
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.
Tumblr media
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.
Tumblr media
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!
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.
Tumblr media
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.”
Tumblr media
(rb, ra, il)
0 notes
risebird · 8 years ago
Text
There is no such thing as serverless
Tumblr media
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
laurelkrugerr · 5 years ago
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
riichardwilson · 5 years ago
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
scpie · 5 years ago
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
secretcupcakesublime · 4 years ago
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
connecticut-seo-adwords · 7 years ago
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