tag:blogger.com,1999:blog-24084792063767266912024-03-24T20:34:49.365-07:00Health to the WebThe web is an amazing wonderful thing and long may it be strong and healthy.Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.comBlogger227125tag:blogger.com,1999:blog-2408479206376726691.post-77056090074117978032024-03-24T10:40:00.000-07:002024-03-24T10:40:14.404-07:00AI Assistants - Kent Dodds, "Ai assistants are a force multiplier" <p><span style="font-family: arial;">"Ai assistants are a force multiplier" "Learn how to use efficiently"</span></p><p><span style="font-family: arial;">I watched Kents Epic dev course (15 mini videos) on how to use AI in your workflow. These are my notes.</span></p><p><span style="font-family: arial;">Customize your AI assistants.</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">the more AI assistants know about you the better</span></li><li><span style="font-family: arial;">chatGpt 4 allows you set "custom instructions", which Kent uses to tell his role (web developer), frameworks & languages used (e.g. remix, typescript), some prettier rules, works on a mac, uses vscode etc.</span></li><ul><li><span style="font-family: arial;">unfortunately this is a chatGpt 4.0 feature (I don't see in 3.5), but I asked chatGpt about it and it recommended you could start the conversation by providing this as context information and provide detailed instructions </span></li><li><span style="font-family: arial;">you can also tell chaGpt how to respond e.g. "terse", "casual", "call me Denis", "consider new technologies and contrarian ideas", "be accurate and thorough" etc.</span></li></ul><li><span style="font-family: arial;">I tried Kents query in 3.5 and it provided a better answer than 4.0 imo "as a web developer how do I convert a form into FormData" (better in that it provided more code...but maybe that was because Kent configured his to "treat me as an expert" and this the AI provided less details?)</span></li></ul><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Making technical decisions with AI</span></div><div><ul style="text-align: left;"><li><span style="font-family: arial;">using an AI assistant can help you think through problems</span></li><li><span style="font-family: arial;">e.g. "</span><span style="background-color: white; color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space-collapse: preserve;">please argue both sides of the cuid versus uuid debate"</span></li><li><span style="background-color: white; color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space-collapse: preserve;">Kent provided a less clear cut more detailed use case where he had a detailed conversation with the AI. Spend time going back and forth</span></li><li><span style="background-color: white; color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; white-space-collapse: preserve;">"a rubber duck which talks back" when making a decision between options</span></li></ul><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;"><br /></span></span></div><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">Exploring unfamiliar topics</span></span></div></div><div><ul style="text-align: left;"><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">instead of googling something, why not try chatGpt instead</span></span></li></ul><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;"><br /></span></span></div></div><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">AI Assistants in editor</span></span></div><div><ul style="text-align: left;"><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">tabnine and cody (sourcegraph) are AI assistance which have been around a while but Kent uses copilot and likes it (and recommends)</span></span></li><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">copilot uses open tabs to understand context, so have relevant code files open</span></span></li><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">in copilot can open chat request with Cmd + I and edit the same chat request text multiple times to refine the request</span></span></li><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">can select specific code, hit Cmd + I and have the AI focus on that code only e.g. select some code and ask AI to write test for it</span></span></li><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">make it feel like a chat, like someone you're pairing with, conversational</span></span></li><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">when writing tests with AI, make sure it fails as expected (as well as passes)</span></span></li></ul><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">AI assistants are great at creating fake data. Kent showed a conversation where he refined the test data and improved it. Does creating fake data "all the time"</span></span></div></div><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;"><br /></span></span></div><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">Simplify api interactions. Write fetch code.</span></span></div><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;"><br /></span></span></div><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">Understand code. Kent typically uses AI assistant to understand code rather than humans these days. AI assistants are really good at helping understand code</span></span></div><div><ul style="text-align: left;"><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">Kent selected code and then asked copilot to explain</span></span></li></ul><div><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif, Helvetica Neue, Arial, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;"><span style="white-space-collapse: preserve;">Understanding API Documentation</span></span></div><div><ul style="text-align: left;"><li><span style="color: #0d0d0d; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; white-space-collapse: preserve;">Kent selected some code to reports Sentry errors and then asked copilot to explain how to filter out browser plugin errors</span></li></ul></div></div><p></p><p><span style="font-family: arial;">Debugging errors by asking to explain error messages</span></p><p><span style="font-family: arial;">Simplify, refine, write SQL queries. Understand syntax.</span></p><p><span style="font-family: arial;">Can use AI to write commit messages. Switched to Source Control view which shows diff changes and btn to commit. Also has an AI btn to generate a commit message. Kent: "I do occasionally use to write commit messages"</span></p><p><span style="font-family: arial;">Understand and respond to Social media (e.g. X). Kent uses to understand and write.</span></p><p><br /></p><p><span style="font-family: arial;">Some take aways for me:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">can edit the same chat request text multiple times to refine the request</span></li><ul><li><span style="font-family: arial;">chat back and forth, keep iterating and refine</span></li></ul><li><span style="font-family: arial;">select code and hit Cmd + I</span></li><li><span style="font-family: arial;">custom instructions in chatGpt4</span></li><li><span style="font-family: arial;">established codebases typically have foundational code for tasks like fetching and a set way of using it, using AI to generate fetch code is often not be very useful imo (because it's already simplified)</span></li><li><span style="font-family: arial;">oh yah, don't trust its answers always, do verify</span></li></ul><div><span style="font-family: arial;"><br /></span></div><div><br /></div><p></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-86951771781771114772024-03-23T22:43:00.000-07:002024-03-23T22:43:57.218-07:00NVIDIA CEO Jensen Huang is impressive<p><span style="font-family: arial;">The more I learn about him, the more Nvidia CEO Jensen Huang impresses me.</span></p><p><span style="font-family: arial;">"No task is beneath me because remember I used to be a dishwasher and I mean that. I used to clean toilets. I've cleaned a lot of toilets. I've cleaned more toilets than all of you combined"</span></p><p><span style="font-family: arial;">- wow! his first job was at Dennys, they have a booth dedicated to him there<br />- from <a href="https://www.youtube.com/watch?v=nVxH-oFV3Yk" target="_blank">this Stanford talk</a></span></p><p><span style="font-family: arial;">An immigrant to the US where he attended high school. Graduated as an electrical engineer from Oregon State Uni 1984. Masters from Stanford in 1992. At age of 30 in 1993 founded Nvidia. Lost 80% of share price in the 2008 Great Recession. But has recovered spectacularly.</span></p><p><span style="font-family: arial;">He has ~40 direct reports. Doesn't understand why a CEO would have only a few reports.<br /></span></p><p><span style="font-family: arial;">"The future of computing will be highly generated. Most of it is intelligence. In the future our computers will behave in that way." Highly generative versus retrieved.</span></p><p><span style="font-family: arial;">"Start from first principals" How would I build it if doing it today?</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><a href="https://www.youtube.com/watch?v=odEnRBszBVI" target="_blank">The Nvidia keynote at GC 2024</a><br /></span><span style="font-family: arial;">- "The rate at which we're advancing computing is insane" "Over the last 8 years increased computation by one thousand times"<br />- Moores law was 10x every 5 years, 100x every 10 years<br />- Nvidia Blackwell chip has 104 billion transmitters and 10 terrabytes interface<br />- Blackwell chip for a Trillion parameter scale generative AI<br />- "We created a processor for the </span><span style="font-family: arial;">generative AI generation"<br />- DGX system supports 720 Peta flops, 130 Terrabytes per second, "more than the aggregate bandwidth of the internet, we could basically send everything to everybody within a second"</span></p><p><span style="font-family: arial;">They create a </span><span style="font-family: arial;">simulation engine</span><span style="font-family: arial;"> a </span><span style="font-family: arial;">virutal world call "Omniverse" for AIs to train and learn. A gym for AIs. Gave an example of a robotics building<br />"Everything that moves will be robotic, there's no question about that"</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">"<span style="background-color: white;"><a href="https://www.technologyreview.com/2017/05/12/151722/nvidia-ceo-software-is-eating-the-world-but-ai-is-going-to-eat-software/" target="_blank">Software is eating the world, but AI is going to eat software.</a>" 2017</span></span></p><p><span style="font-family: arial;"><span style="background-color: white;"><br /></span></span></p><p><span style="font-family: arial;"><span style="background-color: white;"><br /></span></span></p><p><span style="font-family: arial;"><span style="background-color: white;"><br /></span></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-5336758714714445842024-02-17T20:27:00.000-08:002024-03-24T20:34:13.322-07:00Notes on The Turing Lectures: "What is generative AI?"<p><span style="font-family: arial;"> </span><a href="https://www.youtube.com/watch?v=fwaDtRbfioU&list=PLuD_SqLtxSdVDcrCYIHayTL91DapuIHrO&index=3" style="font-family: arial;" target="_blank">The Turing Lectures: What is generative AI?</a></p><p><span style="font-family: arial;">Generative - create new content (audio, code, images, text, video)</span></p><p><span style="font-family: arial;">Artificial Intelligence - automatically using a computer program </span><span style="font-family: arial;">"a lot of myth about it, its just a tool", "we have to spell it out"</span></p><p><span style="font-family: arial;">Generative AI is not a new concept. Google translate (17 yo) is an example of generative AI.</span></p><p><span style="font-family: arial;">Another example is Apples Siri (11yo), another generative AI. </span><span style="font-family: arial;">Phone autocomplete or Google search autocomplete</span></p><p><span style="font-family: arial;">Not that new so "what is the fuss"? Answer: </span><span style="font-family: arial;">chatGpt was launched. </span><span style="font-family: arial;">chatGpt is a lot more sophisticated than older AIs. </span><span style="font-family: arial;">You can have a conversation.</span></p><p><span style="font-family: arial;">The technology is not extremely new. It uses language modeling. Given a context, the language model can predict</span></p><p><span style="font-family: arial;">e.g. context: "I want to"</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">prediction: play, eat, shovel</span></li></ul><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">AIs used to count to predict but latest use Neural Networks. Feed context (prompt text) into neural language model which predicts the answer.</span></p><p><span style="font-family: arial;"><u>Basic steps to build a language model:</u></span></p><p></p><ol style="text-align: left;"><li><span style="font-family: arial;">Step 1. Collect very large data (aka "corpus") e.g. the web (wikipedia books, github, stack overflow)</span></li><li><span style="font-family: arial;">Step 2. Ask language model to predict the next word in a sentence</span></li><ul><li><span style="font-family: arial;">randomly truncate last part of input sentence, calculate probability of missing works, adjust and feedback to the model</span></li><li><span style="font-family: arial;">e.g. "the trevi fountain is in ??" Rome - good Berlin - bad</span></li></ul><li><span style="font-family: arial;">Step 3. Repeat over whole corpus. Keep going over months.</span></li><ul><li><span style="font-family: arial;">So it learns over time by practicing and correcting.</span></li></ul></ol><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">Neural Network Language Models</span></p><p><span style="font-family: arial;">Parameters = # input units * other nodes</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">Transformers - "king of AI architectures"</span></p><p><span style="font-family: arial;"> - uses mini neural networks</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">gpt: "generative pretrained transformer"</span></p><p><span style="font-family: arial;">pre-training how is it done?</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">hire expert trainers who train the AI (correct answers)</span></li><li><span style="font-family: arial;">in the wild, how people respond and provide multiple replies for users to choose</span></li></ul><p></p><p><br /></p><p><span style="font-family: arial;">"Fine tuning" - specializing the network e.g. add medical data to generic pretrained model</span></p><p><span style="font-family: arial;">gpt is fine tuned to be general purpose</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">How can a model become great? "Size matters, bigger is better"</span></p><p><span style="font-family: arial;">Since 2018 model sizes have grown. gpt1 "ant brain" ...now gpt4 has 1 trillion parameters "more than rat brain"</span></p><p><span style="font-family: arial;">The more parameters, the more powerful the AI. When you get to half a billion parameters then "common sense reasoning" and "summarization" and "arithmetic" etc become possible and powerful</span></p><p><span style="font-family: arial;">gpt4 has read almost all the human written text</span></p><p><span style="font-family: arial;">gpt4 cost $100 million, </span><span style="font-family: arial;">openAI can do it because they have Microsoft backing them (not everyone can)</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">"HHH" framework </span><span style="font-family: arial;">i.e. Helpful, Honest and Harmless</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">How do you make the model HHH? You Fine tune it by letting it know if answers are correct or not.</span></li></ul><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">LLMs generate hallucinations by fabricating nonexistent or false facts</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">Llama 2, a chatGpt like model from Meta</span></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-52399049115144739452024-02-12T06:56:00.000-08:002024-03-24T10:40:41.435-07:00a unified theory<p> <span style="font-family: arial;">What a well written and thoughtful post <a href="https://aworkinglibrary.com/writing/unified-theory-of------" target="_blank">A unified theory of </a></span></p><p>"<span style="background-color: white; color: #333333; font-family: chaparral-pro, Georgia, serif; text-indent: 20px;">That’s what work is, after all. Work—the action of change, the movement of energy from one being to another—is the means by which fucks are granted. </span><em style="background-color: white; color: #333333; font-family: chaparral-pro, Georgia, serif; text-indent: 20px;">Good work is the art of giving a fuck about the living.</em><span style="background-color: white; color: #333333; font-family: chaparral-pro, Georgia, serif; text-indent: 20px;"> And all of us, every day, are faced with good work that needs doing, and good work that we can do."</span></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-16964360843958613932023-12-19T18:16:00.000-08:002023-12-19T18:16:16.577-08:00npmtrends is cool<p><span style="font-family: arial;">npmtrends is cool</span></p><p><span style="font-family: arial;">great for researching npm packages, you can enter multiple packages and see some comparison info, checkout the table below including "last updated" and suggested searches</span></p><p><span style="font-family: arial;">e.g. this link compares different react drag'n'drop libraries</span></p><p><span style="font-family: arial;">https://npmtrends.com/@dnd-kit/core-vs-react-beautiful-dnd-vs-react-dnd-vs-react-drag-and-drop-vs-react-draggable-vs-react-file-drop</span></p><p><span style="font-family: arial;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: arial;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjf9cmyVhq4jcu8QdQ1ONW7IQ2FD8reKgOGX6DlxzWMaUtrhXNik6mdOV_t1_OlP9c3skthXm56Ezq6iEf40UQKG-LkqcH9Aec9GyrFC6uCnHLJ_XIyBNYaUsSL0mtVKm256F75XEq1tUFryMOOvFazHxKK5Q5stUOCV_7GO4RFlSBrK7ckAWHVA8UvDRTc" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1176" data-original-width="1086" height="586" src="https://blogger.googleusercontent.com/img/a/AVvXsEjf9cmyVhq4jcu8QdQ1ONW7IQ2FD8reKgOGX6DlxzWMaUtrhXNik6mdOV_t1_OlP9c3skthXm56Ezq6iEf40UQKG-LkqcH9Aec9GyrFC6uCnHLJ_XIyBNYaUsSL0mtVKm256F75XEq1tUFryMOOvFazHxKK5Q5stUOCV_7GO4RFlSBrK7ckAWHVA8UvDRTc=w541-h586" width="541" /></a></span></div><span style="font-family: arial;"><br /><br /></span><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-54247820040850297932023-11-21T19:30:00.000-08:002023-11-22T10:38:34.951-08:00Ye lowly ole' html checkbox<p><span style="font-family: arial;">Ye lowly ole' checkbox</span></p><p><span style="font-family: arial;">Often when developing with frameworks like React we use html elements like checkbox (input type="checkbox") as "connected" controls and don't depend on or avail of the default html behavior </span><span style="font-family: arial;">(by connected, I mean using useState to track the checked/unchecked state of the checkbox). Also worth noting we often use custom components which wrap the html element.</span></p><p><span style="font-family: arial;">But react-router v6.4 and above requires you (using the standard flow of Form to action function handler) to depend on the default/native html element behavior because react-router follows standard web patterns for form handling and submission (which is a good thing).</span></p><p><span style="font-family: arial;">For checkbox that </span><span style="font-family: arial;">native html element behavior </span><span style="font-family: arial;">is:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">use the name attribute to give it a name and if it's checked the name will be submitted in the form data </span></li><ul><li><span style="font-family: arial;">by default if the checkbox is checked when submitted, then the form submitted will contain: <span style="background-color: #eeeeee;"><name>=on</span></span></li><ul><li><span style="font-family: arial;">"on" is just the default html checkbox uses</span></li><li><span style="font-family: arial;">so presence of <name> in the submitted form means unchecked</span></li></ul><li><span style="font-family: arial;">if the checkbox is not checked when submitted then the <span style="background-color: #eeeeee;"><name></span> value will not be present in the form object submitted (absence means checked)</span></li><li><span style="font-family: arial;">in a react-router action handler you can query the form object and see if the <span style="background-color: #eeeeee;"><name></span> of the checkbox control is present as a way to tell if it's checked</span></li></ul><li><span style="font-family: arial;">you can use the <span style="background-color: #eeeeee;">value</span> attribute to set an explicit "on" value, but you don't have to use it</span></li><ul><li><span style="font-family: arial;">e.g. if set <span style="background-color: #eeeeee;">value="newsletter" </span>then when the checkbox is checked the form submitted will contain <span style="background-color: #eeeeee;"><name>=newsletter </span></span></li></ul><li><span style="font-family: arial;">interestingly, the checked attribute is only used for default state on load, if present then the checkbox is checked by default. It does not indicate if the checkbox is currently checked or not and is not changed when user checks and unchecks a checkbox</span></li></ul><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">See <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox" target="_blank">more from mdn here</a></span></div><div><br /></div><div><span style="font-family: arial;">A final comment, typically give each checkbox a unique name. But if you reuse the same name for multiple checkboxes then when submitted it will combine into 1 string of multiple name value pairs!</span></div><div><span style="font-family: arial;">Radio buttons also share name but that's more key to their behavior in that all radios with same name are grouped into a mutually exclusive set.</span></div><div><span style="font-family: arial;"><br /></span></div><p></p><p><span style="font-family: arial;"><br /></span></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-41890522984284067062023-11-08T10:16:00.004-08:002023-11-08T10:16:33.072-08:00Github Universe 2023 keynote<h2 style="text-align: left;"><span style="font-family: arial;">Keynote</span></h2><p><span style="font-family: arial;">Github universe keynote by Thomas Dohmke, CEO</span></p><p><span style="font-family: arial;">Big emphasis on copilot. "Github founded on git. Github refounded on Copilot"</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">55% faster developers</span></li><li><span style="font-family: arial;">37k orgs using it</span></li></ul><p></p><p><span style="font-family: arial;">starting point is copilot, vision is Copilot X, </span></p><p><span style="font-family: arial;">The keynote Copilot chat demo was impressive. The inline chat and diff view was very cool.</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">I've been using the company Instance of chatgpt and I like the conversational style</span></li></ul><p></p><p><span style="font-family: arial;">Bringing Copilot chat to android and ios github mobile and also other ides such as jetbrains</span></p><p><span style="font-family: arial;">Upgraded to GPT-4</span></p><p><span style="font-family: arial;">Copilot integrate to github.com and showed how integrates with PRs. </span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">new icon in PR</span></li><li><span style="font-family: arial;">showed generate tests for PR and added to PR</span></li><li><span style="font-family: arial;">secret scanner</span></li></ul><p></p><p><span style="font-family: arial;">Next presenter talked about "fine tuning" copilot in your github codebase and partner integrations</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">then Accenture cto talked about their use of copilot</span></li></ul><p></p><p><span style="font-family: arial;">CEO of MSFT joins live onstage "we are a platform company"</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">he's an impressive guy, CEO of msft, done amazing for msft</span></li><li><span style="font-family: arial;">turns out MSFT buying github was a genius move (and OpenAI too!)</span></li></ul><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">“one more thing…” on the same stage Steve Jobs introduced the ipad 13 years ago!</span></p><p><span style="font-family: arial;">wow! powerful keynote....wish I was there in person (had a chance of a ticket but could not get transferred in time unfortunately)</span></p><p><span style="font-family: arial;">side note: Thomas is super enthusiastic "fly at the speed of their own minds with copilot" (maybe pouring it in a little heavy eh!)</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-66021058152080323412023-11-05T18:02:00.000-08:002023-11-28T18:35:47.148-08:00call openAI provide github PR feedback hackathon<p><span style="font-family: arial;">For Opentables 2023 October Hackathon I proposed integrating with openAI api to get feedback on github PRs . </span><span style="font-family: arial;">I'd already used the chatGPT interface to get feedback on code or write tests and it's good.</span></p><p><span style="font-family: arial;">I know there are github Actions out there which do similar but I wanted to hack a solution for our companys setup and also to learn. Another engineer thought it was a fun idea and joined me in this hack. </span></p><p><span style="font-family: arial;">My initial idea was to: </span></p><p></p><ol style="text-align: left;"><li><span style="font-family: arial;">create a github Action which triggers off PRs and </span></li><li><span style="font-family: arial;">call github to get the PR code</span></li><li><span style="font-family: arial;">call the openAI chat api and passes it the code</span></li><li><span style="font-family: arial;">call github to add a comment to the PR</span></li></ol><div><span style="font-family: arial;">One challenge with this was that would be running externally and would not have access private data needed to access things.</span></div><div><span style="font-family: arial;">So we pivoted to running the steps inside our CI build system instead. This gave us github triggers such as PR opened and also secure access. To get access to the PR number we had to enable a feature in the CI, but I did and it worked!</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">We used bash scripts and I was able to use curl to call to github to get a PR diff and also use curl to add a comment to a PR. Nice!</span></div><div><span style="font-family: arial;">But calling openAI over bash and escaping data was a real problem and not working. Half way through day 2 of the hack and we did't have a working solution! Not good.</span></div><div><span style="font-family: arial;">So pivot number 2: onwards to python</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">We rewrote the hack in python and within a few hours everything was basically working. </span></div><div><span style="font-family: arial;">When open a PR the code diff is retrieved, send to openAI, get back feedback, add as PR comment and it worked! fantastic</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Our solution is very basic and assumes a happy case of a PR adding a new file. </span></div><div><ul style="text-align: left;"><li><span style="font-family: arial;">How would you support multiple pushes to a PR? Don't want to keep calling openAI and duplicating AI comments.</span></li><li><span style="font-family: arial;">A PR of a totally new file returns a github diff of the new file, but what about a PR with some changes to existing files(s)? What would you get and pass to openAI to make sense of it?</span></li></ul><div><span style="font-family: arial;">Shortly after our Hackathon at the Github universe conference they announced github PR copilot support. They stole our idea! lol</span></div></div><div><span style="font-family: arial;">Not surprised that is added. Have yet to use it myself.</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">The day is close when the first PR reviewer will be copilot and engs won't even look at a PR until the AI feedback is addressed (almost like a linter). How much further is the day when the AI writes the code as well...and no need to review its own code (scary). But that's a different discussion.</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;"><b>Appendix</b></span></div><div><span style="font-family: arial;"><a href="https://docs.github.com/en/rest/pulls/pulls?apiVersion=2022-11-28#get-a-pull-request" target="_blank">github api to get PR</a></span></div><div><span style="font-family: arial;">our call to openAI was basic using model: gpt-3.5-turbo, role: 'user' and content: <the diff text> and <a href="https://platform.openai.com/docs/guides/text-generation/chat-completions-api" target="_blank">chat completions api</a></span><span style="font-family: arial;"><a href="https://platform.openai.com/docs/guides/text-generation/chat-completions-api" target="_blank"> </a> and response is in json content prop</span></div><div><span style="font-family: arial;"><br /></span></div><p></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-54824063216220125122023-06-25T13:33:00.004-07:002023-06-25T13:43:18.729-07:00SEO web basics with Google Search Console<p><span style="font-family: arial;">Let's say you have a friend with a small online business with a website, but their products are not appearing in google search.</span></p><p><span style="font-family: arial;">How would you help them troubleshoot it?</span></p><p><span style="font-family: arial;">You'd probably start by going to the site, understand the products and pages and then run google searches for those products. Does you see results? even if you scroll down lots of results pages?</span></p><p><span style="font-family: arial;">Is there a robots.txt for the site? what rules are specified? are there any exclusions? Check also for any robots meta tag in the html.</span></p><p><span style="font-family: arial;">Is a sitemap.xml provided? What urls are in it?</span></p><p><span style="font-family: arial;">You might also examine the html for the product pages. Are the basics present? title tag, meta tag for description which match the content on the page. Sensible use of h1 etc tags on the page. Useful and accurate content about each product page. Urls which are search friendly.</span></p><p><span style="font-family: arial;">You might run Chrome Lighthouse checking SEO, Performance and Accessibility scores to see if any red flags exist.</span></p><p><span style="font-family: arial;">So you find that your "friends" website products are not appearing in search results. But the in general the site looks like it should be (there are no clear reasons it shouldn't). Then what?</span></p><p><span style="font-family: arial;">You need to use <a href="https://search.google.com/search-console/about" target="_blank">Google Search Console</a>, a tool google provides to allow website owners better understand how google search views their site and pages. Anyone with a website that does business or shared content should be using. note: Google first crawls your pages, then indexes them and then checks if matches user search, so it's a multistep process.</span></p><p><span style="font-family: arial;">To get started you need to add Google Search console file or a tag to your website so that google knows you're the owner and it can share info about the site with you. Adding a tag is easy (they provide instructions).</span></p><p><span style="font-family: arial;">Once added and recognized by google then in Search Console you will see your website and information about it. </span></p><p><span style="font-family: arial;">More details:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">Overview dashboard view shows </span></li><ul><li><span style="font-family: arial;">searches which led to clicks; </span></li></ul><li><span style="font-family: arial;">Performance </span></li><ul><li><span style="font-family: arial;">lots of info on total clicks, total impressions, search result position as well as queries users use, pages hit etc.</span></li><li><span style="font-family: arial;">indexing info on your pages</span></li></ul><li><span style="font-family: arial;">Url inspection</span></li><ul><li><span style="font-family: arial;">enter a url and see in detail what Google Search knows about it. Is it crawled? Is it indexed? What was last crawled etc.</span></li><li><span style="font-family: arial;">test a url to understand if Google has any issues with it</span></li><li><span style="font-family: arial;">request indexing for a url</span></li></ul><li><span style="font-family: arial;">Indexing section</span></li><ul><li><span style="font-family: arial;">Pages: info on indexed pages and reasons why not indexed</span></li><li><span style="font-family: arial;">Sitemap: add a new sitemap</span></li></ul><li><span style="font-family: arial;">Settings</span></li><ul><li><span style="font-family: arial;">manage users and set owner</span></li></ul></ul><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">Google Search Console gives you the insights to troubleshoot website pages and understand how google search views you pages. Google provides lots of docs and videos to learn more about the <a href="https://support.google.com/webmasters/topic/9456557?hl=en&ref_topic=4558844&sjid=2331533645107689660-NA" target="_blank">reports in Google Search Console</a></span></p><p><span style="font-family: arial;">Now you can troubleshoot. Is google search finding and crawling my pages? Are there indexing issues or not? How does search rank my pages versus others? What kinds of searches drive traffic to my site? and from where?</span></p><p><span style="font-family: arial;">Then you can start fine tuning your site such as <a href="https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data" target="_blank">using structured data</a>, <a href="https://developers.google.com/search/docs/appearance/title-link" target="_blank">best practices for setting title links</a>. Lots of things you can do to improve ranking. A process of identifying improvements, making changes and then measuring outcomes (and repeat).</span></p><p><span style="font-family: arial;"><a href="https://developers.google.com/search/docs/fundamentals/get-on-google" target="_blank">Google Search Central </a>is a great resource for learning (google wants you on their search results, win for them, win for you)</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">Sitemaps - sitemap.xml, a file in which you provide information about pages on your site and their relationships. Not required by google search (if pages are linked properly) but can make crawling more efficient. Good to provide for a new site and has few external links. You can upload sitemap files in google search console in the sitemap section.</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">tools like <a href="http://www.xml-sitemaps.com">www.xml-sitemaps.com</a> offer free generator service (up to 500 pages), then you pay for more. Very easy to use</span></li><li><span style="font-family: arial;">I've also used <a href="https://github.com/lgraubner/sitemap-generator-cli" target="_blank">sitemap-generator-cli</a> a nodejs tool to run locally against a site</span></li></ul><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">Overview<span> page</span></span></p><p><span style="font-family: arial;"></span></p><div class="separator" style="clear: both; text-align: left;"><span style="font-family: arial;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh74wAP4ZilG1KEDGY7ylj7jKo4ZJ0CQPJtB_d3S0XnmLIXok6KjTE7NibNwR5X5G91hjlrjlKolvApdTaImMuKj1cwtHZUPRkyc_QHS-c-yVM_O7_DB4a1xF3CTyhvZXXjHSSX5MPAB9UDTWWlx5xh1V8Yv9jJD0kk8uwu8O1A49djI_Y-mgzuSeFyZ7z7" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1022" data-original-width="1388" height="313" src="https://blogger.googleusercontent.com/img/a/AVvXsEh74wAP4ZilG1KEDGY7ylj7jKo4ZJ0CQPJtB_d3S0XnmLIXok6KjTE7NibNwR5X5G91hjlrjlKolvApdTaImMuKj1cwtHZUPRkyc_QHS-c-yVM_O7_DB4a1xF3CTyhvZXXjHSSX5MPAB9UDTWWlx5xh1V8Yv9jJD0kk8uwu8O1A49djI_Y-mgzuSeFyZ7z7=w425-h313" width="425" /></a></span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: arial;"><br /></span></div><div class="separator" style="clear: both; text-align: left;"><span style="font-family: arial;">Performance</span></div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: left;"><span style="font-family: arial;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhKwkpf9E27rpwEVFRmFwidlki8IcT0sZUYm1_FcZDFPRwAEq7hFPOxZpICMicUfZGfjU3l0_lI9eEeXQjUFjgfG0XhHmJkWc7uSgpDwZtm-WIHwR-p4DqfXLOTABfNmaMKjJaY2ND2McX0i70eRcgX6W9mYdvdeblMNI2DLI0l0juOAyo8RXMM4cOfHZ2S" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1031" data-original-width="1617" height="282" src="https://blogger.googleusercontent.com/img/a/AVvXsEhKwkpf9E27rpwEVFRmFwidlki8IcT0sZUYm1_FcZDFPRwAEq7hFPOxZpICMicUfZGfjU3l0_lI9eEeXQjUFjgfG0XhHmJkWc7uSgpDwZtm-WIHwR-p4DqfXLOTABfNmaMKjJaY2ND2McX0i70eRcgX6W9mYdvdeblMNI2DLI0l0juOAyo8RXMM4cOfHZ2S=w442-h282" width="442" /></a></span></div><span style="font-family: arial;"><br /><br /></span></div><p><span style="font-family: arial;"><span style="font-family: arial;"><br /></span></span></p><span style="font-family: arial;">Indexing -> Pages</span><p></p><p><span style="font-family: arial;"></span></p><div class="separator" style="clear: both; text-align: left;"><span style="font-family: arial;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEjY7HpCckqD2KhT2Zi2Z9ABPJLR-SXPry_9unZlZbrLeF77RRLd9n7VC1EDLinLt4_dEGBWW7uAdQWzueYWZBfS3ucBDdWhFKf1ue-ln6pKtRAQRa8wBMBd8-FHycazTsszKYHT4v_YY3hNKXvwY9je_Mm82aoI_n_fi2SWdsk_N1Drs2YXV6K13T-JtV3F" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="1090" data-original-width="1393" height="333" src="https://blogger.googleusercontent.com/img/a/AVvXsEjY7HpCckqD2KhT2Zi2Z9ABPJLR-SXPry_9unZlZbrLeF77RRLd9n7VC1EDLinLt4_dEGBWW7uAdQWzueYWZBfS3ucBDdWhFKf1ue-ln6pKtRAQRa8wBMBd8-FHycazTsszKYHT4v_YY3hNKXvwY9je_Mm82aoI_n_fi2SWdsk_N1Drs2YXV6K13T-JtV3F=w426-h333" width="426" /></a></span></div><span style="font-family: arial;"><br /><br />URL inspection</span><p></p><p><span style="font-family: arial;"></span></p><div class="separator" style="clear: both; text-align: left;"><span style="font-family: arial;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiXxs3eL9lMs6U71EN74AbVtaEwz3eU9e7POWXjK0bwH8hQrxOaKMUiVZdpNqaepcU9wRrQyKPvY5IYZV24g9QAwqZPsSEQh_Da03M-NnmveJiQ3ELQzJu-OYxMXnTMVFK3TXBV8jP2lQoP4EocE3AD83tP44-xjGRjE0Cv1zETkq1IIzKScGJq0JSG6oYx" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="973" data-original-width="1624" height="274" src="https://blogger.googleusercontent.com/img/a/AVvXsEiXxs3eL9lMs6U71EN74AbVtaEwz3eU9e7POWXjK0bwH8hQrxOaKMUiVZdpNqaepcU9wRrQyKPvY5IYZV24g9QAwqZPsSEQh_Da03M-NnmveJiQ3ELQzJu-OYxMXnTMVFK3TXBV8jP2lQoP4EocE3AD83tP44-xjGRjE0Cv1zETkq1IIzKScGJq0JSG6oYx=w457-h274" width="457" /></a></span></div><span style="font-family: arial;"><br /><br /></span><p></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-42338471417184196882023-06-18T11:32:00.005-07:002023-06-25T13:35:24.346-07:00How to communicate technical & cognitive complexity?<p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">"An idea is more cognitively complex if it causes you to hold more concepts in mind and think about how they relate to each other. A simple example of this is the number of moves and countermoves available in Checkers vs. Chess." It's a measure of how hard something is to understand.</span></span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">Not recognizing complexity up front is one of the biggest frustrations for teams. I've seen teams think a problem is simpler than it is and/or not want to dig into the details which led to large overruns and significant stress on teams. It can make or break a team.</span></span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">It's not an exact science but there are strategies.</span></span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">First, how do you recognize? some data points</span></span></p><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;"> how many concepts are involved? </span></span></p></li><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">e.g. building a responsive multi form layout for a user profile to be used in multiple different apps each of which wants to highlight slightly different data/functionality has more concepts involved than a single use table view.</span></span></p></li><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">e.g. supporting different billing address rules by 16 locale/region (line 1, line2, city, state, zip, postal, region etc.)</span></span></p></li></ul></ul><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;"> how many systems are involved?</span></span></p></li><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">e.g. for a project in 2020 it required changes to 7+ systems (salesforce, finance, FE & BE etc.)</span></span></p></li></ul></ul><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;"> how many teams are involved?</span></span></p></li><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">e.g. same onboarding example, there were all the technical teams plus legal, billing, marketing business</span></span></p></li></ul></ul><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;"> skill level and experience level of your team</span></span></p></li><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;"> a difficult problem for less experienced/new team may be easier for experienced established team</span></span></p></li></ul></ul><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">significance: significant and new, significant unknowns e.g. using "for of" loops may be new (or not ;-)) but it's not significant</span></span></p></li><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">architecture: how critical is it to the architecture</span></span></p></li><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">importance and urgency of the product; critical or high urgency features may not be the best for experimentation, they could be but they may not be</span></span></p></li><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">risk: what's the risk to the initiative if it fails? are you all in and have no plan b</span></span></p></li></ul><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">spikes and POCs are good techniques to learn more about the problem domain and also allocate time to do R&D; </span></span></p></li><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">ask other engineers for their opinions. You're not alone and there's a lot of experience around OT. Just sharing with others can be a big help to gain clarity and get opinions & ideas </span></span></p></li></ul><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">An irony is following the Agile process can make it feel harder to have the time to dig into a problem. But you can take time to do r&d and better understand the problem domain in Agile, spike tickets are a way to accommodate that.</span></span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">Represent the complexity and communicate</span></span></p><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">you need to have data to backup the explanation; it can't just be gut feel</span></span></p></li><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">spreadsheets (yes spreadsheets!) can be a useful way to capture complexity eg from international billing address example list all the fields and locale by locale rules e.g. zip in US is 5 or 9 numeric but as postal code in UK is alphanumeric</span></span></p></li><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">architecture diagrams, sequence diagrams etc. can help explain the complexity; I like the C4 model</span></span></p></li><li aria-level="2" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: circle; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 0pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">task breakdown of work to be done (helps people get an idea of what's involved)</span></span></p></li></ul></ul><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">When discussing its best to talk in terms of Risk and Priorities. It's important to understand what Product, Design & Mgt priorities are. Maybe something I think is complex & important is not as important and can thus be simplified.</span></span></p><p dir="ltr" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">Maybe something simple is more complex because it has the opportunity for reuse or significant advantage if done in a certain way</span></span></p><p><span style="font-family: arial;"><span id="docs-internal-guid-db7583e4-7fff-d846-1152-efb8186b60c9"></span></span></p><ul style="margin-bottom: 0px; margin-top: 0px; padding-inline-start: 48px;"><li aria-level="1" dir="ltr" style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; list-style-type: disc; text-decoration: none; vertical-align: baseline; white-space: pre;"><p dir="ltr" role="presentation" style="line-height: 1.2; margin-bottom: 0pt; margin-top: 10pt;"><span style="background-color: transparent; color: #353744; font-style: normal; font-variant: normal; font-weight: 400; text-decoration: none; vertical-align: baseline; white-space: pre-wrap;"><span style="font-family: arial;">explain the value: maybe what you're building is more than the minimum necessary but will save other teams having to rebuild it</span></span></p></li></ul><div><span style="color: #353744; font-family: arial;"><span style="white-space-collapse: preserve;"><br /></span></span></div><div><span style="color: #353744; font-family: arial;"><span style="white-space-collapse: preserve;"><br /></span></span></div><div><span style="color: #353744; font-family: arial;"><span style="white-space-collapse: preserve;"><br /></span></span></div>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-82117033419597429722023-04-30T20:00:00.001-07:002023-05-01T10:15:01.023-07:00react-intl plurals and select<p><span style="font-family: arial;">I gotta say I love <a href="https://formatjs.io/docs/core-concepts/icu-syntax/#plural-format" target="_blank">react-intl plural support</a> for internationalizations.</span></p><p><span style="font-family: arial;">Its easy to use and works</span></p><p><span style="font-family: arial;">e.g. "Top {num}% of customers in the past {period} {period, plural, one {month} other {months}}"</span></p><p><br /></p><p><span style="font-family: arial;">The <a href="https://formatjs.io/docs/core-concepts/icu-syntax/#select-format" target="_blank">`{select}` feature</a> is pretty cool too. Can use for either or choices as well as multiples.</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-70059563397810137132023-03-04T12:02:00.001-08:002023-03-06T11:06:44.013-08:00leave warnings for unsaved changes<p><span style="font-family: arial;">User Scenario:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">As a user who edits xyz properties, when I leave the page then I should see a warning prompt to leave and lose changes or stop leaving and remain. </span></li></ul><p></p><p><span style="font-family: arial;">This is a typical scenario and the approach to handle has not changed in a long time. So lets review it.</span></p><p><span style="font-family: arial;">But first what are some of the ways a user could "leave" the page</span></p><p></p><ol style="text-align: left;"><li><span style="font-family: arial;">reload the page</span></li><li><span style="font-family: arial;">browser back button</span></li><li><span style="font-family: arial;">navigation action to a different url than this app </span></li><li><span style="font-family: arial;">edit url in the address bar and hit enter</span></li><li><span style="font-family: arial;">close the tab</span></li><li><span style="font-family: arial;">close the browser</span></li><li><span style="font-family: arial;">navigation action to a different url within this app</span></li><li><span style="font-family: arial;">close app modal with edits & unsaved changes</span></li><li><span style="font-family: arial;">considering mobile it gets more complicated because there are other lifecycle events. On Android and iOS mobile apps can be started and stopped as needed by the OS, which is not something web has historically had to deal with. Web has typically just had to deal with user initiated events</span></li></ol><div><span style="font-family: arial;">Choices 1-6 are all similar: unloading the web page/single page app and are commonly handled using <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event" target="_blank">window beforeunload event</a> </span></div><div><ul style="text-align: left;"><li><span style="font-family: arial;">mdn note: "<span style="background-color: white; color: #1b1b1b; font-size: 16px;">Especially on mobile, the </span><code style="border-radius: var(--elem-radius); box-sizing: border-box; color: #1b1b1b; font-size: var(--type-smaller-font-size); padding: 0.125rem 0.25rem; width: fit-content;">beforeunload</code><span style="background-color: white; color: #1b1b1b; font-size: 16px;"> event is not reliably fired." - e.g. on mobile user visits page but switches to another app and late OS closes the page (see more on new dom events such as visibilitychanged)</span></span></li></ul></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Choice 7 & 8 represents actions which don't reload the page, such as a navigation event within a single page app. These will not fire the window beforeunload event and need to be handled differently.</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">To avail of beforeunload, you typically add a listener to window "beforeunload" event and in the callback call preventDefault on the event passed and set returnValue on the event to a string or similar and return that. </span></div><div><span style="font-family: arial;">Don't forget to remove the listener when finished.</span></div><div><ul style="text-align: left;"><li><span style="font-family: arial;">typically calling preventDefault and setting returnValue is only done if there are unsaved changes on the page (so you need some way to know if changes have happend and when they are reset such as when saved)</span></li><li><span style="font-family: arial;">when you do stop the default action then the browser will automatically show a prompt to stay or leave</span></li><ul><li><span style="font-family: arial;">you have no control over this prompt, styling or message content, and it looks different across browsers</span></li></ul><li><span style="font-family: arial;">not enough to call preventDefault, you have to also set event returnValue and return it; in older browsers the value in returnValue was displayed but not any more in more modern browsers</span></li><li><span style="font-family: arial;">as mentioned, advice on usage is evolving, one of chromes recommendation is to use beforeunload with caution and <a href="https://developer.chrome.com/blog/page-lifecycle-api/#the-beforeunload-event" target="_blank">never add beforeunload listener unconditionally.</a> Instead, add it when there are unsaved changes and remove it once changes are saved</span></li></ul></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">We're using the latest version of <a href="https://reactrouter.com/en/main" target="_blank">react-router</a> v6.8 and a data router and they (finally) added some support for handling this scenario with their new <a href="https://reactrouter.com/en/main/hooks/use-before-unload" target="_blank">useBeforeUnload() hook</a>. But honestly it's very basic and <a href="https://github.com/remix-run/react-router/blob/746dc480bf496e5fa8a4fe45e4059bdedee2a5b6/packages/react-router-dom/index.tsx#L1243" target="_blank">just a wrapper around window beforeunload</a> (disappointed). I tracked a long thread about why it was left out, then finally added back and I know the react-router team didn't want to add it back due to various complexities etc. but the community wanted it. What they implemented reflects their reluctance imo. It also adds the listener unconditionally and does not provide the fine grained control to add and remove as Chrome recommends (see above).</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">There are new lifecycle events being added to support mobile and more sophisticated resource management even on web. <a href="https://developer.chrome.com/blog/page-lifecycle-api/" target="_blank">This is a good post on the topic from chrome</a>. New dom events such as visibilitychange and freeze provide new ways to respond to changes in app state. But for our needs and user base, for now we will continue to use beforeunload for the basic case of warning of unsaved changes.</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Re new events, transitioning to hidden state (visibilitychange event) is considered likely to end a users session and is the recommended event to key off to: 1. persist unsaved application state 2. send any analytics and 3. stop any background tasks. Freeze dom event is another trigger to stop using resources (important in a mobile context).</span></div><div><span style="font-family: arial;">But beforeunload is still the appropriate event to use to warn & prompt a user of unsaved changes when unloading the page (with prior cavet about when to add and remove listeners).</span></div><div><span style="font-family: arial;"> </span></div><div><span style="font-family: arial;"><br /></span></div><div><b><span style="font-family: arial;">references</span></b></div><div><span style="font-family: arial;">https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event</span></div><div><span style="font-family: arial;">https://developer.chrome.com/blog/page-lifecycle-api/</span></div><div><span style="font-family: arial;">Older 2015, but interesting: https://www.igvita.com/2015/11/20/dont-lose-user-and-app-state-use-page-visibility/</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Safari Leave warning (same as Reload warning) </span><span style="font-family: arial;">built in prompts</span></div><div><span style="font-family: arial;"><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgN6_qMI5MMw-h-pY88HXgJgGMV9zfarQ5BJvwnu-VSrCfVn6pV7hpwfYJG_2RJ-dYtl3gO-v_qIYfZGMPtaoZXyrZfI-iFb5jdlEoMBBUrydQZV3dnWms12FSivbb8ll9EB5khXw-oFtWcJ0_JtINk7V45k7iebPNkwHr82LAqwPstup5KnVFyFcDc_A" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="219" data-original-width="263" height="228" src="https://blogger.googleusercontent.com/img/a/AVvXsEgN6_qMI5MMw-h-pY88HXgJgGMV9zfarQ5BJvwnu-VSrCfVn6pV7hpwfYJG_2RJ-dYtl3gO-v_qIYfZGMPtaoZXyrZfI-iFb5jdlEoMBBUrydQZV3dnWms12FSivbb8ll9EB5khXw-oFtWcJ0_JtINk7V45k7iebPNkwHr82LAqwPstup5KnVFyFcDc_A=w274-h228" width="274" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">Edge Reload and Leave built in prompts</div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEhiu06cwXo8JmIXfsJID-4C3pPrtm9Eeq12BOgRsrwzf0mzXxNZJi6LGT3ZM2CEMtamk_B-t2DDHt1NumH_MbRKckes1hGsaTr0c5VLXUyuByJGYdD3UI6L7cFPY95WVpJQQz8qgAYIuIBKEbV75EhGCK8qZZ6z40X5LfUm6U_2AjxnpksUus3mZsyVYw" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="422" data-original-width="540" height="189" src="https://blogger.googleusercontent.com/img/a/AVvXsEhiu06cwXo8JmIXfsJID-4C3pPrtm9Eeq12BOgRsrwzf0mzXxNZJi6LGT3ZM2CEMtamk_B-t2DDHt1NumH_MbRKckes1hGsaTr0c5VLXUyuByJGYdD3UI6L7cFPY95WVpJQQz8qgAYIuIBKEbV75EhGCK8qZZ6z40X5LfUm6U_2AjxnpksUus3mZsyVYw=w241-h189" width="241" /></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEh2oTW6Gnxlueg2D41nfipKgs3V6I259maqi-YmohUl0Xt1C9QUYlGGXI21yyEuQS3M1elcP1KW99dXOoto_ks_iNNndUS4-JoO8Ndo8B5aJ4l7Bp1qHvRNg4GecutSLoUnK4jB4-s_3Nae1IFa5kL_bP_SIV6Y_t5d4ILkBb0uX7cEsOPXLApulFfENw" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img alt="" data-original-height="410" data-original-width="530" height="187" src="https://blogger.googleusercontent.com/img/a/AVvXsEh2oTW6Gnxlueg2D41nfipKgs3V6I259maqi-YmohUl0Xt1C9QUYlGGXI21yyEuQS3M1elcP1KW99dXOoto_ks_iNNndUS4-JoO8Ndo8B5aJ4l7Bp1qHvRNg4GecutSLoUnK4jB4-s_3Nae1IFa5kL_bP_SIV6Y_t5d4ILkBb0uX7cEsOPXLApulFfENw=w241-h187" width="241" /></a></div><br />Chrome Reload and Leave</div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg-ZEY71PUreGlneb0Yt8_KcOCt8TA6pMfv3ggo_GnqlbPvO0-LZsrenl7ByM3irQ2e4x-DOm9CPx68Io4fEZZCY_KWtxkkX-i5sX9LT0uM_3VA1r3dYx3YnHo4CJnwu8lu0WsuAQ45yOfMWKbf0pglfYmV4I00JS_sfrMOhdMY5UtPUc25AM2GA4TsHA" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="207" data-original-width="261" height="186" src="https://blogger.googleusercontent.com/img/a/AVvXsEg-ZEY71PUreGlneb0Yt8_KcOCt8TA6pMfv3ggo_GnqlbPvO0-LZsrenl7ByM3irQ2e4x-DOm9CPx68Io4fEZZCY_KWtxkkX-i5sX9LT0uM_3VA1r3dYx3YnHo4CJnwu8lu0WsuAQ45yOfMWKbf0pglfYmV4I00JS_sfrMOhdMY5UtPUc25AM2GA4TsHA=w234-h186" width="234" /></a><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi7Ncek5ehjURyj5JFNGAj7NOIPEanb5PWjnY5IRFG3Rbb6Iex_YXYU1JqLuI6Xir8wodQ5VIKQyvXtmzo9wkPZPglI4rwtJiX27Edh0jsG3OGcdEJTaGQBTfnWWeDTpopmJ-OUn-jQWvnzkc_PeSMv1zhjOxmH4QxGraJKnB2vzoajYa7wDU_gFBia3Q" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img alt="" data-original-height="202" data-original-width="259" height="185" src="https://blogger.googleusercontent.com/img/a/AVvXsEi7Ncek5ehjURyj5JFNGAj7NOIPEanb5PWjnY5IRFG3Rbb6Iex_YXYU1JqLuI6Xir8wodQ5VIKQyvXtmzo9wkPZPglI4rwtJiX27Edh0jsG3OGcdEJTaGQBTfnWWeDTpopmJ-OUn-jQWvnzkc_PeSMv1zhjOxmH4QxGraJKnB2vzoajYa7wDU_gFBia3Q=w238-h185" width="238" /></a><br /><br /></div><br /><br /></div><br /><br /></span></div><div><span style="font-family: arial;"><br /></span></div><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><br /></span></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-75322754646226071272023-03-02T12:11:00.001-08:002023-03-02T12:11:21.783-08:00floating ui - a js library for floating elements such as popover and dropdown<p><span style="font-family: arial;">this is a cool library which an be used for tooltips, menu btn activator etc </span></p><p><span style="font-family: arial;">https://floating-ui.com/</span></p><p><span style="font-family: arial;">https://floating-ui.com/docs/react-examples</span></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-5754108167054668792023-02-23T04:54:00.003-08:002023-02-23T04:54:35.743-08:00UX research resources including W3C and Nielsen and examples for accessible ui controls<p> </p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><b>Nielsen Norman Group</b> is a good resource for <a href="https://www.nngroup.com/articles/" target="_blank">UX research articles</a></span></p><p><span style="font-family: arial;">e.g. <a href="https://www.nngroup.com/articles/split-buttons/" target="_blank">SplitButton guidance</a></span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;"><b>Bootstraps</b> split button implementation: https://getbootstrap.com/docs/5.2/components/dropdowns/#split-button</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">notice the html</span></li></ul><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;"><b>Material UI</b> is another good resouce for UX and compoents. Here's their <a href="https://mui.com/material-ui/react-accordion/" target="_blank">Accordion implementation</a></span></div><div><br /></div><div><br /></div><div>For web accessibility the W3C has good guides:</div><div><ul style="text-align: left;"><li><a href="https://www.w3.org/WAI/ARIA/apg/" target="_blank">Main page</a></li><li><a href="https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/" target="_blank">Read this first</a></li><li>Their <a href="https://www.w3.org/WAI/ARIA/apg/patterns/" target="_blank">patterns page </a>is a good resource e.g. <a href="https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-datepicker/" target="_blank">Date Picker combobox</a>, <a href="https://www.w3.org/WAI/ARIA/apg/patterns/tabs/" target="_blank">Tabs pattern</a> </li><li>For quick lookup by control, checkout <a href="https://www.w3.org/WAI/ARIA/apg/example-index/" target="_blank">the index</a></li></ul></div><div><span style="font-family: arial;"><br /></span></div><div><a href="https://www.sliderrevolution.com/resources/css-toggle-switch/"><span style="font-family: arial;">Interesting css for toggle btn</span></a></div><p></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-42177734550675711022023-02-10T13:49:00.011-08:002023-02-23T05:06:24.607-08:00react-select stacking order bug, z-index, layers and stacking<div style="text-align: left;"><p style="text-align: left;"><span style="font-family: arial; font-size: medium;">Had to fix a tricky bug related to react-select recently (our Dropdown component wraps react-select).</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;">Here's the how the bug manifested. Dropdown does not overlay dynamically added content below it</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: arial; font-size: medium;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy57vVwIK_J59XwsfWRXqupJx7F-XnhlBe3UO-kUn2KGsyRFiNRPzC47fg51zPY8ePV90HMxD8KX87Q8seNEpHsOMmnRGzxh3oA8N137tzQV5pYfy1zYFdfZjMLNv9cXlHZipX44mVHTnlYss2b-PEni0UFeoPabWtPvkng1wJaOpE_5ZO7hW8W7nt3g/s595/zIBug.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="330" data-original-width="595" height="177" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy57vVwIK_J59XwsfWRXqupJx7F-XnhlBe3UO-kUn2KGsyRFiNRPzC47fg51zPY8ePV90HMxD8KX87Q8seNEpHsOMmnRGzxh3oA8N137tzQV5pYfy1zYFdfZjMLNv9cXlHZipX44mVHTnlYss2b-PEni0UFeoPabWtPvkng1wJaOpE_5ZO7hW8W7nt3g/s320/zIBug.jpg" width="320" /></a></span></div><span style="font-family: arial; font-size: medium;"><br /><div class="separator" style="clear: both; text-align: center;"><br /></div>Variations of this have been <a href="https://github.com/JedWatson/react-select/issues/1537" target="_blank">reported</a> since 2017. But I tried all the suggestions in the comments and none worked for me.</span><p></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;">I also tried wrapping the Dropdown in a div and changing z-index to be higher as well as making absolute position but no success. Changing the elements order in the html source and then reordering using flexbox order does work but it breaks the tabbing flow and is not recommended from an accessibility standpoint.</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;">One issue is the Dropdown is in a container and is constrained by the containers z-index. No matter how I change the Dropdowns z-index, its container is stacked below the next in stacking order.</span></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;">Google Chrome debugger layers tool provides a cool way to visualize layers. Could be better but helps, check it out below. You have to look closely but you can see how adjacent layers are stacked.</span></p><p style="text-align: left;"><span style="font-size: medium;"><span style="font-family: arial;">Ultimately the </span><span style="font-family: arial;">z-index</span><span style="font-family: arial;"> of the </span><span style="font-family: arial;">container the Dropdown was in needed to set set higher than subsequent containers (not just the Dropdown but the whole container it's it)</span></span></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;"><br /></span></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;">Google Chrome layers</span></p><p style="text-align: left;"></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn8-RBKhQ-Q3mNNeQ_EpDdVN0PC2mVPQ7JrLS3ZL6iJ-6HQiGLvlTPj1EGHPbJYiY_sO9-L7OuF1yT6j-cxg8KS98kFYs4t3k82OXUFMPPeTNnLjM5GkSrN46Q7pOs2u5F4TNGbf0eI_PVXMh0vRRDrw9LeXuAAy-dipiKJKAl4jiRiyw1Lb_miTXnYA/s999/layersAfter.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="478" data-original-width="999" height="232" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn8-RBKhQ-Q3mNNeQ_EpDdVN0PC2mVPQ7JrLS3ZL6iJ-6HQiGLvlTPj1EGHPbJYiY_sO9-L7OuF1yT6j-cxg8KS98kFYs4t3k82OXUFMPPeTNnLjM5GkSrN46Q7pOs2u5F4TNGbf0eI_PVXMh0vRRDrw9LeXuAAy-dipiKJKAl4jiRiyw1Lb_miTXnYA/w485-h232/layersAfter.jpg" width="485" /></a></div><br /><span style="font-family: arial; font-size: medium;"><br /></span><p></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: arial; font-size: medium;"><br /></span></div><span style="font-family: arial; font-size: medium;"><br /></span><p></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;"><br /></span></p><p style="text-align: left;"><span style="font-family: arial; font-size: medium;"> </span></p><p style="text-align: left;"><span style="font-size: medium;"><span style="font-family: arial;">This may be <a href="https://web.dev/learn/css/z-index/" target="_blank">the best article I read about z-index and stacking</a>. This also <a href="https://www.smashingmagazine.com/2009/09/the-z-index-css-property-a-comprehensive-look/" target="_blank">a good article </a>by smashing magazine. Also <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index">good docs on mdn</a> as usual.</span></span></p><p style="text-align: left;"></p><p></p><p style="text-align: left;"></p><p style="text-align: left;"></p><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">z-index is stack level (or order) of html elements on the x-axis (which is a 3rd axis besides x and y)</span></li></ul><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">there is a natural default order for stacking html elements and the z-index property can change that natural order</span></li></ul><ul><li><span style="font-family: arial; font-size: medium;">by default the order in the html source determines z axis position</span></li></ul><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">if not flexbox or grid then z-index only works on an element whose position property is set to <b>absolute, fixed or relative</b>; (not all position choices, just those 3) </span></li></ul><ul><li><span style="font-family: arial; font-size: medium;">setting z-index on elements without position property set does nothing</span></li></ul><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">if flexbox or grid then can set z-index without setting position</span></li></ul><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">z-index can be negative, positive or auto (same stack order as parent)</span></li></ul><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">negative z-index works only if the element which contains it has z-index value of auto then can set child behind it</span></li></ul><p></p><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">a <b>stacking context</b> is a group of elements with the same parent and and the z-index of all children is based on (relative to) the parents z-index (so also move and down the z-index together)</span></li><ul><li><span style="font-family: arial; font-size: medium;">setting `position: relative` will create a new stacking context for that element</span></li><li><span style="font-family: arial; font-size: medium;">but these properties also do: opactity, will-change and transform</span></li><li><span style="font-family: arial; font-size: medium;">and in the case of flex and grids you just set the z-index value and that will work</span></li></ul></ul><p></p><p></p><p></p><p></p><div><span style="font-family: arial; font-size: medium;"><br /></span></div></div>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-704223811226270502023-02-04T16:47:00.008-08:002023-02-04T16:47:58.118-08:00advice on using react memoization: useMemo, useCallback<p><span style="font-family: arial; font-size: medium;">I like the "new" <a href="https://beta.reactjs.org/" target="_blank">react beta docs</a>, lots more info, real helpful info. Well written, good examples, lots of details. Helping me learn & improve.</span></p><p><span style="font-family: arial; font-size: medium;">The docs have very <a href="https://beta.reactjs.org/reference/react/useMemo" target="_blank">helpful guidance for useMemo </a>and when to use</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">use useMemo to cache expensive calculations, don't use for non expensive calculations</span></li><li><span style="font-family: arial; font-size: medium;">"In general, unless you’re creating or looping over thousands of objects, it’s probably not expensive"</span></li><li><span style="font-family: arial; font-size: medium;">if "time adds up to a significant amount (say, 1ms or more), it might make sense to memoize that calculation" I like the example they show for taking measurements.</span></li></ul><span style="font-size: medium;"><span style="font-family: arial;">Why? blanket use of us</span><span style="font-family: arial;">eMemo (or useCallback) is not harmful but the "code becomes less readable", it also adds to cognitive overhead and does add another function.</span></span><p></p><p><span style="font-family: arial; font-size: medium;">"Optimizing with useMemo is only valuable in a few cases"</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">the calculation is noticeably slow and dependencies rarely change</span></li><ul><li><span style="font-family: arial; font-size: medium;">you should know it's slow before you optimize with useMemo</span></li><li><span style="font-family: arial; font-size: medium;">check your dependencies, log every time the useMemo is regenerated, I've seen useMemo usages which were pointless because a dependency changed so often.</span></li></ul><li><span style="font-family: arial; font-size: medium;">you pass as a prop to a component wrapper in memo</span></li><li><span style="font-family: arial; font-size: medium;">the value is a dependency of some hook</span></li></ul><p></p><p><span style="font-family: arial; font-size: medium;"><br /></span></p><p><span style="font-family: arial; font-size: medium;">The docs have similar guidance which can be applied to <a href="https://beta.reactjs.org/reference/react/useCallback" target="_blank">useCallback</a>, which is also a memoization. In many cases you don't need it. Again the docs call out a few use cases for useCallback:</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial; font-size: medium;">you pass to a component wrapped in memo</span></li><li><span style="font-family: arial; font-size: medium;">the useCallback result is a dependency to another hook</span></li><li><span style="font-family: arial; font-size: medium;">if you’re writing a custom Hook, it’s recommended to wrap any functions that it returns into useCallback</span></li></ul><p></p><div><br /></div>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-6654594222544530872023-01-05T13:12:00.004-08:002023-01-05T13:12:35.940-08:00laugh: This is a motherf***ing website<p>https://motherfuckingwebsite.com/</p><p><span style="background-color: #f8f8f8; color: #1d1c1d; font-family: Slack-Lato, Slack-Fractions, appleLogo, sans-serif; font-size: 15px; font-variant-ligatures: common-ligatures;">they do a really good job hiding all the complexity 🤣</span></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-25920135594277992882022-12-23T12:03:00.004-08:002022-12-29T12:06:12.174-08:00web components and how we used<h2 style="text-align: left;"><span style="font-family: arial;">Web components</span></h2><p><span style="font-family: arial;">"Web Components is a suite of different technologies allowing you to create reusable custom elements — with their functionality encapsulated away from the rest of your code — and utilize them in your web apps." - MDN</span></p><h3 style="text-align: left;"><span style="font-family: arial;">3 main technologies</span></h3><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">Custom elements: define behavior of the component </span></li><li><span style="font-family: arial;">Shadow DOM: a shadow dom is rendered separately from the main document dom, and thus isolated</span></li><ul><li><span style="font-family: arial;">you can create a custom element with a shadow dom </span></li></ul><li><span style="font-family: arial;">HTLM Templates write markup templates</span></li></ul><p></p><h3 style="text-align: left;"><span style="font-family: arial;">steps to build your own web component</span></h3><h4 style="text-align: left;"><span style="font-family: arial;">write the class</span></h4><p></p><ol style="text-align: left;"><li><span style="font-family: arial;">create a js class for your element which inherits from HTMLElement</span></li><ul><li><span style="font-family: arial;">define a constructor with call to super()</span></li></ul><li><span style="font-family: arial;">register it with the CustomElementRegistry object e.g. customElements.define("word-count", WordCount, { extends: "p" });</span></li><ul><li><span style="font-family: arial;">the extends is optional, but shows you can extend from existing elements and use like so: <p is="word-count"></span></li><li><span style="font-family: arial;">terminology update: when extending it called "Custom built in"</span></li></ul></ol><p></p><h4><span style="font-family: arial;">add behavior by adding lifecycle methods to your class</span></h4><p></p><ol style="text-align: left;"><li><span style="font-family: arial;"><u>connectedCallback</u>() - called each time is appended into a document-connected element</span></li><ol><li><span style="font-family: arial;">typically the place to add render behavior</span></li><li><span style="font-family: arial;">this is where to code dom apis</span></li><li><span style="font-family: arial;">attach to shadowRoot using: </span></li><ol><li><span style="font-family: arial;">shadow.innerHTML = `<p>hi<p>`;</span></li><li><span style="font-family: arial;">or: shadow.append(htmlFragment)</span></li></ol></ol><li><span style="font-family: arial;"><u>disconnectedCallback</u>() - called when disconnected form documents DOM</span></li><li><u style="font-family: arial;">observedAttributes</u><span style="font-family: arial;">() - used to specify list of attributes to watch</span></li><ol><li>for react folks think props</li></ol><li><u style="font-family: arial;">attributeChangedCallback()</u><span style="font-family: arial;"> - called when when one of the custom element's attributes is added, removed, or changed</span></li><ol><li>notice you get the name as well as old and new values attributeChangedCallback(name, oldValue, newValue) </li></ol></ol><p></p><p></p><h4 style="text-align: left;"><span style="font-family: arial;">add styles</span></h4><span style="font-family: arial;">You can attach styles inline or as a link element to the shadowRoot</span><p></p><p><span style="font-family: arial;">To attach styles inline</span></p><p></p><span style="font-family: arial;"><ul style="text-align: left;"><li><span style="font-family: arial;">document.createElement("style");</span></li><li><span style="font-family: arial;">style.textContent = `.my-class { }`;</span></li><li><span style="font-family: arial;">shadow.append(syle, htmlFragment)</span></li></ul></span><p><span style="font-family: arial;">To attach styles as linked file</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">link: document.createElement("link"); </span></li><li><span style="font-family: arial;">shadow.appendChild(linkElem);</span></li></ul><p></p><p><span style="font-family: arial;"><br /></span></p><h4 style="text-align: left;"><span style="font-family: arial;">libraries to make this easier</span></h4><p><span style="font-family: arial;">Lit - https://lit.dev/</span></p><p><span style="font-family: arial;">Stencil - https://stenciljs.com/</span></p><p><span style="font-family: arial;"><br /></span></p><p><span style="font-family: arial;">Here's a gist example use of<a href="https://gist.github.com/denisos/1bbf9336171379bdd7e19b50e2cd8524#file-examplewebcomponent-tsx" target="_blank"> web components to render html from another source in a shadow dom</a>.</span></p><p><br /></p><h3 style="text-align: left;"><span style="font-family: arial;">helpful resources</span></h3><p><span style="font-family: arial;">https://developer.mozilla.org/en-US/docs/Web/Web_Components</span></p><p><span style="font-family: arial;">https://www.youtube.com/watch?v=vLkPBj9ZaU0</span></p><p><span style="font-family: arial;">https://css-tricks.com/building-interoperable-web-components-react/</span></p><p><span style="font-family: arial;">shadow dom: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM</span></p><p><span style="font-family: arial;">https://bradfrost.com/blog/post/lets-talk-about-web-components/?ck_subscriber_id=1697731036</span></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-49125287086984316082022-12-17T18:00:00.053-08:002023-02-04T16:58:36.761-08:00Elon, twitter and all that<p><span style="font-family: arial; font-size: medium;">I don't have a problem with making moves to make your business a success. Cutting failing products. Pivoting. Laying people off. Staying lean. Cutting perks. That's all part of business (especially tech). I and the whole SF office were laid off from a startup in Thanksgiving 2015. Sucked. It happens. We all accepted it and moved on. And I accept that in some cases employees have been overly lavished with perks (although I would like to see how free lunches, laundry etc. compares to executive compensation packages).</span></p><p><span style="font-size: medium;"><span style="font-family: arial;">But how Elon Musk has done it, treating people as disposable and abusable. Forcing people to work round the clock. Ritualistic styled humiliations such </span><span style="font-family: arial;">as sign up to be "hardcore" or be fired,</span><span style="font-family: arial;"> </span><span style="font-family: arial;">fired if disagree with Elon, </span><span style="font-family: arial;">print out your code, send screenshots of your code in an email and come to present. </span></span><span style="font-family: arial; font-size: large;">I don't get how that makes sense? </span><span style="font-family: arial; font-size: large;">I mean, all our code is online in github, why print it off and hand deliver? How is someone going to grok thousands of lines of printed code? Who pores over code on paper instead of using digital tools like studio code for code reviews? </span></p><p><span style="font-size: medium;"><span style="font-family: arial;">How do I parent my kid(s) if I have to sleep in the office? </span><span style="font-family: arial;">What choice do I have if I'm on a temporary visa? Have financial or other commitments? Many people just have to hang on and try take the crap doled out.</span></span></p><p><span style="font-family: arial; font-size: medium;">Watching this unfold has put in my mind for some time that Musks truly bad behavior is empowering others to do some bad behavior themselves. The nytimes had an article about how Musks behavior is making him a hero to some in Silicon Valley. </span><span style="font-family: arial; font-size: large;">"Time to kick some a**". </span><span style="font-family: arial; font-size: large;">I really hope most people realize you can run a business and also be ethical and respect people.</span></p><p><span style="font-family: arial; font-size: medium;">I remember decades ago an exec at a company I worked at saying something like "I can't wait for all these programmers to be on the street with begging bowl in hand". Thankfully that person is long gone and the software industry has only grown stronger. It will get past this latest bs too. There's a lot more good actors out there who respect peoples dignity, know how to lead and also run a business. How about we put more of them in the news?</span></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-10716656556176790032022-11-30T17:29:00.002-08:002022-12-27T10:48:00.205-08:00 css: vertical-align: middle;<p><span style="font-family: arial;"> <span color="rgba(var(--sk_raspberry_red,224,30,90),1)" style="font-variant-ligatures: none; white-space: pre-wrap;">vertical-align: middle;</span></span></p><div style="text-align: left;"><span><span style="font-family: arial; font-variant-ligatures: none; white-space: pre-wrap;">"The vertical-align CSS property sets vertical alignment of an inline, inline-block or table-cell box." <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align" target="_blank">mdn docs</a></span></span></div><div style="text-align: left;"><span style="font-family: arial;"><span><span style="font-variant-ligatures: none; white-space: pre-wrap;"><br /></span></span><span><span style="font-variant-ligatures: none; white-space: pre-wrap;">nice!</span></span></span></div>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-33842295302483656092022-11-26T22:04:00.006-08:002022-11-26T22:04:39.538-08:00notes on the "webs next transition" post by kent dodds<p><span style="font-family: arial;">Kent writes about <a href="https://www.epicweb.dev/the-webs-next-transition?" target="_blank">the webs next transition</a> (Oct '22)</span></p><p><span style="font-family: arial;">Tech which powers the web (http, html, js, css) were all developed over 25 years ago (eek!)</span></p><p><span style="font-family: arial;">Major architectural patterns over that time</span></p><p></p><ol style="text-align: left;"><li><span style="font-family: arial;">multi page apps (MPA); the era of html pages, java server pages</span></li><ol><li><span style="font-family: arial;">all code (persistence, data fetching & mutation, rendering, routing) runs on server except UI interaction in browser </span></li><li><span style="font-family: arial;">cons: full page refreshes and ui feedback control</span></li><li><span style="font-family: arial;">pro: simple architecture and code management</span></li></ol><li><span style="font-family: arial;">progressively enhanced multi page apps (PEMPAs); the era of jquery, mootools etc</span></li><ol><li><span style="font-family: arial;">code including rendering runs on server and UI both (if no js then fallback to MPA mode</span></li><li><span style="font-family: arial;">pro: improved UI interaction, more control on FE</span></li><li><span style="font-family: arial;">con: more complex architecture, code management, code duplication</span></li></ol><li><span style="font-family: arial;">single page apps; era of backbone, angular, ember, react, vue</span></li><ol><li><span style="font-family: arial;">routing, data fetching & mutation code is on both server and FE but only rendering and UI Feedback on the FE</span></li><li><span style="font-family: arial;">pro: less code on server (most all routing on FE, rendering on FE), more FE control</span></li><li><span style="font-family: arial;">con: exploding bundle size, fetch waterfalls, runtime performance (lots of js to run), complex state mgt </span></li></ol><li><span style="font-family: arial;">...the next transition... <- guessing this is what Kent will blog about</span></li></ol><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Kent introduces the new architectural pattern #4: </span><span style="font-family: arial;"><u>Progressively Enhanced Single Page Apps</u> (PESPA) - a mix of SPA and MPA</span></div><div><ul style="text-align: left;"><li><span style="font-family: arial;">"The primary benefit of Progressive Enhancement is not that "your app works without JavaScript" (though that's a nice side-benefit) but rather that the mental model is drastically simpler."</span></li><li><span style="font-family: arial;">BE code and FE code are the exact same, shared enabled by using a library which supports this (...ok Kent I see where this is going...)</span></li><li><span style="font-family: arial;">FE mutates data and sends as a form submission to the action listed on the form which is sent to the BE code which does persistence etc. and sends back success/fail response which triggers a redirect or re-render</span></li></ul><div><span style="font-family: arial;">"What distinguishes a PESPA:</span></div></div><p></p><div><div><ul style="text-align: left;"><li><span style="font-family: arial;">Functional is the baseline - JS used to enhance not enable</span></li><li><span style="font-family: arial;">Lazy loading + intelligent pre-fetching (more than just JS code)</span></li><li><span style="font-family: arial;">Pushes code to the server</span></li><li><span style="font-family: arial;">No manual duplication of UI code (as in PEMPAs)</span></li><li><span style="font-family: arial;">Transparent browser emulation (#useThePlatform)"</span></li></ul><div><span style="font-family: arial;"><br /></span></div></div></div><div><span style="font-family: arial;">Kent writes that Remix is leading the charge for PESPAs, the first framework out of the box to offer full support for Kents vision of PESPA. Remix is a bridge across the network.</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">I'm thinking Remix will be big. It's a powerful model which addresses challenges with SPAs. </span></div><div><span style="font-family: arial;">It's also built by the guys who brought us react-router which has been downloaded over 1bn times. That is significant because </span><span style="font-family: arial;">react-router v6.4 now provides implementations of Remix concepts like loaders and actions and use of form element for for submissions (but without the Remix server side support). The developers who did all those 1bn download is a big ready audience who could be easily migrated to the newest react-router as a "gateway" to remix.</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Kent also includes an interesting looking reference to an analysis of "<a href="https://frontendmastery.com/posts/the-new-wave-of-javascript-web-frameworks/" target="_blank">the new wave of javascript web frameworks</a>"</span></div><p></p><div><br /></div><p></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-83103450292335319932022-11-04T10:03:00.006-07:002022-12-23T12:07:54.526-08:00using react-chartjs to create a clickable bar chart<p><span style="font-family: arial;">chartjs is a popular (58k github stars) charting library which supports many different kinds of charts</span></p><p><span style="font-family: arial;"><a href="https://react-chartjs-2.js.org/" target="_blank">react-chartjs</a> is a wrapper for chartjs for react apps. It provides a number of components such as Bar which are easy to use to create charts.</span></p><p><span style="font-family: arial;">I used </span><span style="font-family: arial;">react-chartjs 2 days ago to create a clickable bar chart for our hackathon project and it's pretty freaking awesome.</span></p><p><span style="font-family: arial;">I have 1 simple dataset and needed each bar to be clickable. Took less than 2 hours to use </span><span style="font-family: arial;">react-chartjs and learn how to get it working. Others on the team were using D3 and that has a much steeper learning curve (although very powerful).</span></p><p><span style="font-family: arial;">Here's what my chart looks like. Each bar is clickable and calls an onClick handler I passed to the Bar component.</span></p><p><span style="font-family: arial;"></span></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiG8UgwlXnZlursN5Ds9gNhqZ9KUrPcbCfTj7skSxIcm3qH5RsjbzxyJYfYMbznwczITECCyU6-qYzJVcMIIP_Ha6bkjs-dAxzEj-HYfk6meWBurEb2bli4rKH6I-bT5-YZExUif-mrx2lefcOAHRIJjUyquvJ87Ej6lkO97altAi1jU_OnVvgtuM1frg" style="margin-left: 1em; margin-right: 1em;"><img data-original-height="297" data-original-width="1211" height="157" src="https://blogger.googleusercontent.com/img/a/AVvXsEiG8UgwlXnZlursN5Ds9gNhqZ9KUrPcbCfTj7skSxIcm3qH5RsjbzxyJYfYMbznwczITECCyU6-qYzJVcMIIP_Ha6bkjs-dAxzEj-HYfk6meWBurEb2bli4rKH6I-bT5-YZExUif-mrx2lefcOAHRIJjUyquvJ87Ej6lkO97altAi1jU_OnVvgtuM1frg=w640-h157" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><br /><p></p><p><span style="font-family: arial;">I followed this <a href="https://react-chartjs-2.js.org/examples/vertical-bar-chart">react-chartjs example</a> but had just 1 dataset (instead of 2 as in the example). </span></p><p><span style="font-family: arial;">Here's a <a href="https://gist.github.com/denisos/5b22a3dba0fec7cc58f6f566e9d40672">gist of the code </a>(I modified a larger file so apologies for any mistakes) which has what you'll need to get it setup and working.</span></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-49513444388103795222022-10-30T11:16:00.002-07:002022-10-30T11:16:31.822-07:00nextjs conf 2022 notes<p><span style="font-family: arial;"><a href="https://nextjs.org/conf">nextjs conf 2022</a> just completed </span></p><p><span style="font-family: arial;">"dynamic without limits" "ship dramatically less javascript to the client"</span></p><p><span style="font-family: arial;">keynote talked about 3 areas of innovation in nextjs 13</span></p><p></p><ol style="text-align: left;"><li><span style="font-family: arial;">tooling - moving from webpack to turboprop (they'r next gen build tooling written in rust, not js) </span></li><ul><li><span style="font-family: arial;">nextjs hired the creator of webpack to build their next gen tooling: turbopack</span></li><li><span style="font-family: arial;">nextjs 13 with turbopack starts up in 1.8 secs for a large app with 3k components, versus 6.3 secs with nextjs 12 and webpack</span></li><li><span style="font-family: arial;">the larger the app the better it compares in performance</span></li><li><span style="font-family: arial;">check it out on turbo.build</span></li><li><span style="font-family: arial;">turbopack could be the "killer app" for nextjs</span></li></ul><li><span style="font-family: arial;">routing and rendering (a new nextjs router)</span></li><ul><li><span style="font-family: arial;">worked with react core team to create a new loader api</span></li></ul><li><span style="font-family: arial;">components</span></li><ul><li><span style="font-family: arial;">images support; images are a large part of web packs so nextjs helps developers with lazy image loading</span></li><ul><li><span style="font-family: arial;">next/image</span></li></ul><li><span style="font-family: arial;">custom fonts; brand new font system to optimize fonts and remove connection requests</span></li><ul><li><span style="font-family: arial;">next/font</span></li></ul><li><span style="font-family: arial;">img and font changes help to avoid layout shifts</span></li><li><span style="font-family: arial;">social cards; generate dynamic social cards</span></li></ul></ol><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">nextjs has raised over $300 million in investment and are putting that to work</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">Annnnnd in the other corner we have remix (made by the creators of react-router which has over 1bn downloads and thus a massive possible audience of developers). Remix is newer than nextjs and does not provide tooling support, but for next gen react web dev these two frameworks look to be the primary choices.</span></div><div><span style="font-family: arial;"><br /></span></div><div><span style="font-family: arial;">p.s. </span><span style="font-family: arial;">I love the nextjs dark side of the moon prism logo, but am not a fan about the grays and blacks everyone presenting is wearing and even in the furniture in the background! </span></div><p></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-13848611554338117462022-10-23T10:33:00.002-07:002023-03-02T12:05:29.667-08:00react-router v6.4+ loaders, actions, forms and more<h2 style="text-align: left;"><span style="font-family: arial;">react-router </span></h2><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">react-router is used for in app single page app navigation, we configure routes for pages in the app to map to components</span></li><li><span style="font-family: arial;">react-router has over 1bn downloads, its an industry standard (but there are others e.g. Nextjs router)</span></li><li><span style="font-family: arial;">many apps use react-router, many on v5.x</span></li></ul><h3 style="text-align: left;"><span style="font-family: arial;">the new react-router 6.4.x</span></h3><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">the newest major version of react router v6.4 is a significant enhancement which adds a lot of new features. react-router v6.4 offers new features to load data (loaders) and handle actions (actions). </span></li><ul><li><span style="font-family: arial;">It's done gone all Remix-y which makes sense because the same guys wrote both.</span></li></ul><li><span style="font-family: arial;">eliminates a lot of boilerplate code to fetch data in useEffect() and set various loading states</span></li><li><span style="font-family: arial;">put your data load and update logic in react-route components instead of custom code</span></li><li><span style="font-family: arial;">unlike Remix, react-router v6.4 is still just all on the client (not server like Remix)</span></li></ul><h3 style="text-align: left;"><span style="font-family: arial;">paradigm shifts</span></h3><p><span style="font-family: arial;">Lets start with a couple of high level ideas; "back to the future" so to speak OR "what's old is new again"</span></p><p></p><ol style="text-align: left;"><li><span style="font-family: arial;">back to web basics, react-router v6.4 uses “web standards” mental model of page loading and form submission</span></li><ul><li><span style="font-family: arial;">forms, methods and actions, Request, formData, ids and more</span></li><li><span style="font-family: arial;"><a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data" target="_blank">this mdn doc is a good place </a>to re-learn</span></li><li><span style="font-family: arial;">forms and actions will probably be a big part of your app</span></li><li><span style="font-family: arial;">uncontrolled controls, don't have to control with react if you don't need to (often do, but don't have to)</span></li></ul><li><span style="font-family: arial;">"groove is in the heart" and “state is tied to the url” instead of global state redux</span></li><ul><li><span style="font-family: arial;">model app state in the url</span></li><li><span style="font-family: arial;">e.g. configure routes and have then code Forms to submit to those </span></li><ul><li><span style="font-family: arial;">list: path="/myapp/users"</span></li><li><span style="font-family: arial;">view: path="/myapp/users/:userid"</span></li><li><span style="font-family: arial;">edit: path="/myapp/users/:userid/edit"</span></li><li><span style="font-family: arial;">delete: path="/myapp/users/:userid/delete"</span></li><li><span style="font-family: arial;">for example, see: https://reactrouter.com/en/main/start/tutorial#deleting-records</span></li></ul></ul></ol><h3 style="text-align: left;"><span style="font-family: arial;">more details on features</span></h3><p style="text-align: left;"><span style="font-family: arial;">data loading<br /></span></p><ul style="text-align: left;"><li><span style="font-family: arial;">provides data loading hooks to initiate data loading during a navigation (https://reactrouter.com/en/main/start/overview#data-loading)</span></li><li><span style="font-family: arial;">new loader property in a Route, which takes a fn which allows you to load data (return a promise)</span></li><li><span style="font-family: arial;">then the data is available using their useLoaderData() hook</span></li><li><span style="font-family: arial;">so no need to write fetch code in useEffects to load data</span></li></ul><p><span style="font-family: arial;">data mutation</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">new action property in a Route which takes a function, new Form and new fetcher.Form</span></li><li><span style="font-family: arial;">meant to handle mutations e.g. create/edit/delete</span></li><li><span style="font-family: arial;">typically connect a react-router Form and action to map to an action (just like you would a regular html form)</span></li><li><span style="font-family: arial;">see example: https://reactrouter.com/en/main/start/overview#data-mutations</span></li></ul><p><span style="font-family: arial;">enable this to start with by using a new "data router" to support these loaders and actions (data apis), use createBrowserRouter and optionally createRoutesFromElements </span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">see https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis</span></li><li><span style="font-family: arial;">new data router is similar to previous versions but a new RouterProvider replaces BrowserRouter and is passed routes created by createBrowserRouter() </span></li><li><span style="font-family: arial;">you could put routes in the route config under the /routes folder (or /pages folder); though the Error element page is not a route</span></li></ul><p></p><p><span style="font-family: arial;">actions and loaders are also "a thing" in remix, which is now brought over to react-router, but unlike remix, in react-router loaders & actions run on the client, not the server</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">the same guys who created react-router also created remix (Michael Jackson, Ryan Florence)</span></li><li><span style="font-family: arial;">yes, you can continue to use react-router using BrowserRouter and not use loaders, actions and more (but react-router recommends upgrading)</span></li></ul><p><span style="font-family: arial;">form handling</span></p><p></p><ul style="text-align: left;"><li><span style="font-family: arial;">HTML form submissions cause a navigation in the browser, just like clicking a link. react-router Form prevents the browser sending the request to the server (as normal) and instead sends it to the route action instead</span></li><li><span style="font-family: arial;"><span style="font-family: arial;">"By convention, React Router uses this (the Form POST submission) as a hint to automatically revalidate the data on the </span>page after the action finishes. That means all of your useLoaderData hooks update and the UI stays in sync with your data automatically! Pretty cool."</span></li><li><span style="font-family: arial;">set names in the form fields so can get referenced to extract the vales</span></li><li><span style="font-family: arial;">action receives a standard web request object which has a formData() method which can be used to get form values</span></li><li><span style="font-family: arial;">so something like this code:</span></li></ul><p></p><p><span style="font-family: arial;"><Form method="post"></span></p><p><span style="font-family: arial;"> <button type="submit">New</button></span></p><p><span style="font-family: arial;"></Form></span></p><p><span style="font-family: arial;">...will route to your action method defined for that route</span></p><p><span style="font-family: arial;">export async function action() {</span></p><p><span style="font-family: arial;"> await createContact();</span></p><p><span style="font-family: arial;">}</span></p><p><span style="font-family: arial;">...after you add that action as an action on the Route config</span></p><p><span style="font-family: arial;"> action: action,</span></p><p><span style="font-family: arial;">Did you know you can have a form submission button outside of a form and link it to the form? you can, using the html id of the form and then matching that to a buttons form value! That's html innit!</span></p><p><br /></p><h2 style="text-align: left;"><span style="font-family: arial;">references</span></h2><p><span style="font-family: arial;">react-router docs, very good tutorial: https://reactrouter.com/en/main/start/tutorial</span></p><p><span style="font-family: arial;">tutorial: https://www.youtube.com/watch?v=L2kzUg6IzxM</span></p><p><span style="font-family: arial;">code: https://github.com/remix-run/react-router/blob/746dc480bf496e5fa8a4fe45e4059bdedee2a5b6/packages/react-router-dom/index.tsx</span></p><p><span style="font-family: arial;"><br /></span></p><pre data-filename="src/routes/root.jsx" data-lang="jsx" data-line-numbers="true" style="--tw-ring-color: rgba(57,146,255,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 #0000; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border-radius: 0.5rem; border: 0px solid rgb(200, 200, 200); box-sizing: border-box; color: var(--base05); line-height: 1.625; margin-bottom: 1rem; margin-top: 1rem; overflow-wrap: normal; overflow: auto; padding: 1rem 0px;"><code style="--tw-ring-color: rgba(57,146,255,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 #0000; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-skew-x: 0; --tw-skew-y: 0; --tw-text-opacity: 1; --tw-translate-x: 0; --tw-translate-y: 0; border-radius: initial; border: 0px; box-sizing: border-box; color: rgb(18 18 18/var(--tw-text-opacity)); display: inline; line-height: inherit; margin: 0px; overflow-wrap: normal; overflow: visible; padding: 0px; word-break: normal;"><span><span class="codeblock-line" data-highlight="true" data-line-number="11" style="--tw-ring-color: rgba(57,146,255,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 #0000; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 #0000; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 #0000; --tw-shadow: 0 0 #0000; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(200, 200, 200); box-sizing: border-box; display: block; padding-right: 1rem; position: relative;"><span style="font-family: arial;"><br /></span></span></span></code></pre>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0tag:blogger.com,1999:blog-2408479206376726691.post-8196309124418661072022-10-09T21:37:00.014-07:002022-11-27T21:44:01.142-08:00free beginners typescript course by Matt Pocock<p>Matts a good teacher and an expert on typescript. He released a <a href="https://www.totaltypescript.com/tutorials/beginners-typescript" target="_blank">free typescript beginners course</a> and I wanted to check it out.</p><p>18 exercises in all and you can complete the exercises in the browser. It's basics but listen to the solutions videos and you'll always pickup something new from Matt</p><p></p><ul style="text-align: left;"><li>with typescript you're declaring the contract and when using typescript think about where you want the contract to be (contract enforcement), thus when declare variables make sure they match the contract </li><li>union type: you OR e.g. a | b | c // a or b or c "everywhere in typescript", "define types of data flowing through your app"</li><li>intersects: you combine type e.g. a & b & c // all 3 combined as a new type</li><li>specifying arrays, 2 ways 1. square brackets (Posts[]) or generics Array<Post> </li><li>lesson 9 and onwards gets more interesting</li><li>return type of a fn which returns a Promise should be a Promise which wraps what will be resolved e.g. Promise<Person></li><ul><li>but could also type the response e.g. const data: Person = await fetch(....)</li><li>that typing is preferable to casting using "as"</li></ul><li><br /></li><li>define key and value of a map: const cache: { [id: string]: string } = { "1": "apples", "2": "oranges" };</li><ul><li>you can also use built in Record e.g. const cache: Record<string, string> = {};</li></ul><li><br /></li><li>use typeof to narrow down what a variable is e.g. if (typeof amount === 'object') { ...its an object }</li><li><br /></li><li>typing a try catch: could cast inside catch e.g. (e as Error).message</li><li> - but better is to do inside catch if (e instanceof Error) return e.message</li></ul><p></p><p></p><ul style="text-align: left;"><li>typing functions</li></ul><p></p><p><span> </span><span> </span><span> </span>type FocusListener = (isFocussed: boolean) => void</p><p><span> </span><span> </span><span> </span>const addListener = (onFocusChanged: FocusListener) => {</p><p><span> </span><span> </span><span> </span><span> </span>}</p><p></p><ul style="text-align: left;"><ul><li>when type a function to return void means you don't have to return anything, if typed return as undefined then would need to return undefined</li></ul></ul><p></p><p><br /></p><p><br /></p><p>reminder: access autocomplete in vscode using ctrl + space</p><p><br /></p><p><a href="https://www.typescriptlang.org/cheatsheets" target="_blank">pretty useful ts cheatsheet</a></p><p><br /></p><p><br /></p>Denishttp://www.blogger.com/profile/07698693743295193006noreply@blogger.com0