<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sam</title>
    <description>The latest articles on DEV Community by Sam (@samsonsham).</description>
    <link>https://dev.to/samsonsham</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F810069%2F7cd826fa-2378-4269-ac58-8d84fa664d81.png</url>
      <title>DEV Community: Sam</title>
      <link>https://dev.to/samsonsham</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/samsonsham"/>
    <language>en</language>
    <item>
      <title>How to setup Next.js project with TypeScript, ESLint and Prettier</title>
      <dc:creator>Sam</dc:creator>
      <pubDate>Thu, 03 Mar 2022 23:06:47 +0000</pubDate>
      <link>https://dev.to/samsonsham/how-to-setup-nextjs-project-with-typescript-eslint-and-prettier-1apk</link>
      <guid>https://dev.to/samsonsham/how-to-setup-nextjs-project-with-typescript-eslint-and-prettier-1apk</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Have you ever struggled what packages should be installed to set up a project? Should I install &lt;code&gt;eslint-config-airbnb&lt;/code&gt; or &lt;code&gt;eslint-config-airbnb-base&lt;/code&gt;? What is &lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&gt;? Is it still needed to install &lt;code&gt;eslint-plugin-react&lt;/code&gt; and &lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;When I start doing research, I have seen people installed a pile of packages. I always question do I really need them all.&lt;/p&gt;

&lt;p&gt;It's good to have a cheat sheet to follow so that every time we can create a clean new project with all toolkits ready. Here is mine for a Next.js project.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;VS Code Config&lt;/strong&gt; part is based on this post &lt;a href="https://rohit.page/blog/posts/how-to-get-prettier-eslint-play-nicely-with-vscode/" rel="noopener noreferrer"&gt;How to get ESlint and Prettier to play nice in VS Code?&lt;/a&gt; From which a new setting of &lt;code&gt;codeActionsOnSave&lt;/code&gt; is introduced.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Toolkits:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Typescript&lt;/li&gt;
&lt;li&gt;ESLint&lt;/li&gt;
&lt;li&gt;Prettier&lt;/li&gt;
&lt;li&gt;Editor Ruler (80,100,120, color: hotpink)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Pre-requisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;li&gt;VS Code plugin: &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt;, &lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;, &lt;a href="https://marketplace.visualstudio.com/items?itemName=rohit-gohri.format-code-action" rel="noopener noreferrer"&gt;Format Code Action&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  VS Code Config
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Cmd + Shift + P&lt;/code&gt; to open Command Palette&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;setting&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Select &lt;code&gt;Preferences: Open Settings (JSON)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add below config:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.rulers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workbench.colorCustomizations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"editorRuler.foreground"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#FF69B4"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.defaultFormatter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"esbenp.prettier-vscode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.codeActionsOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source.formatDocument"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source.fixAll.eslint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Create new project
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/basic-features/typescript" rel="noopener noreferrer"&gt;Next.js - TypeScript&lt;/a&gt;&lt;br&gt;
Run below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest &lt;span class="nt"&gt;--ts&lt;/span&gt; &amp;lt;MY_APP_NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the flag &lt;code&gt;--ts&lt;/code&gt;, Typescript related packages like &lt;code&gt;@types/node&lt;/code&gt; and &lt;code&gt;@types/react&lt;/code&gt; would be included. File extension would become &lt;code&gt;.tsx&lt;/code&gt; instead of &lt;code&gt;.jsx&lt;/code&gt;. A file &lt;code&gt;tsconfig.json&lt;/code&gt; which is used by Typescript compiler would be prepared and with a list of default setting like &lt;code&gt;"target": "es5"&lt;/code&gt; and &lt;code&gt;"strict": true&lt;/code&gt;. &lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up ESLint
&lt;/h2&gt;

&lt;p&gt;Since version 11.0.0, Next.js already integrated  ESLint. We neither have to install ESLint package nor create &lt;code&gt;.eslintrc.json&lt;/code&gt; file manually.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eslint-config-next&lt;/code&gt; could be found in &lt;code&gt;package.json&lt;/code&gt; which below 3 recommended rule-set are used.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;eslint-plugin-react&lt;/li&gt;
&lt;li&gt;eslint-plugin-react-hooks&lt;/li&gt;
&lt;li&gt;eslint-plugin-next&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can check &lt;a href="https://github.com/vercel/next.js/blob/canary/packages/eslint-config-next/index.js" rel="noopener noreferrer"&gt;eslint-config-next&lt;/a&gt; for more details (It's even included &lt;code&gt;@typescript-eslint/parser&lt;/code&gt; and &lt;code&gt;jsx-a11y&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: jsx-a11y is a static AST checker for accessibility rules on JSX elements. &lt;a href="https://www.npmjs.com/package/eslint-plugin-jsx-a11y" rel="noopener noreferrer"&gt;npm web site&lt;/a&gt; shows its supported rules.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So, I am happy with the built-in parser and rule-sets but it lacks the airbnb style. According to &lt;a href="https://nextjs.org/docs/basic-features/eslint" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;, it is not recommended to install overlapping ESLint plugin&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This eliminates the risk of collisions or errors that can occur due to importing the same plugin or parser across multiple configurations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I only install &lt;code&gt;eslint-config-airbnb-base&lt;/code&gt; additionally then should be good to go.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; eslint-config-airbnb-base
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;airbnb-base&lt;/code&gt; to &lt;code&gt;.eslintrc.json&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"next/core-web-vitals"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"airbnb-base"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: &lt;strong&gt;eslint-config-airbnb&lt;/strong&gt; is a collection of a bunch of plugins including &lt;code&gt;eslint-plugin-import&lt;/code&gt;, &lt;code&gt;eslint-plugin-react&lt;/code&gt;, &lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt;, and &lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&gt; while &lt;strong&gt;eslint-config-airbnb-base&lt;/strong&gt; is only the core part of airbnb style.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you want to customise the rules, set the rule to &lt;code&gt;warn&lt;/code&gt; or &lt;code&gt;off&lt;/code&gt; manually in &lt;code&gt;.eslintrc.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"extends"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"next/core-web-vitals"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"airbnb-base"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"no-unused-vars"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"warn"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Setting up Prettier
&lt;/h2&gt;

&lt;p&gt;Now VS Code will alert you with the error underline. We want Prettier to help format our code nicely.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fc5xc1x6srka%2Fscreenshot%2Fscreen_vscode_GzrOutHhttD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fc5xc1x6srka%2Fscreenshot%2Fscreen_vscode_GzrOutHhttD.png" alt="screen"&gt;&lt;/a&gt;&lt;br&gt;
So we create a new file &lt;code&gt;.prettierrc&lt;/code&gt;. And add below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"singleQuote"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Should I specify parser in Prettier?&lt;/strong&gt;&lt;br&gt;
From &lt;a href="https://prettier.io/docs/en/options.html#parser" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prettier automatically infers the parser from the input file path, so you shouldn’t have to change this setting.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Side Dish&lt;/strong&gt;&lt;br&gt;
Prettier has not yet format long string. There is a &lt;a href="https://github.com/prettier/prettier/issues/4123" rel="noopener noreferrer"&gt;discussion on break strings&lt;/a&gt; in Prettier community &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fc5xc1x6srka%2Fscreenshot%2Fscreen_vscode_QT2fGZtg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fik.imagekit.io%2Fc5xc1x6srka%2Fscreenshot%2Fscreen_vscode_QT2fGZtg8.png" alt="screen"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope you have got some basic ideas what packages we already have by default and minimised the amount of packages to be installed for basic setup. Now I have a clean project with all the toolkits I need and without packages that might cause collision. &lt;/p&gt;

&lt;p&gt;After all, you should only install those as &lt;code&gt;devDependencies&lt;/code&gt; and won't affect the size of production build (For Typescript, I am not sure. Official doc recommends to install globally, but someone in &lt;a href="https://github.com/loopbackio/loopback.io/issues/509" rel="noopener noreferrer"&gt;this discussion&lt;/a&gt; said global install would be an anti-pattern. What do you think? Do you install typescript globally or locally, and why? Please let me know).&lt;/p&gt;




&lt;h2&gt;
  
  
  Things to think about
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;As Prettier formats your code on save, some files like &lt;code&gt;_app.tsx&lt;/code&gt; won't be formatted unless you open it and save it once. You can run the command &lt;code&gt;npm run lint&lt;/code&gt; to lint whole project so that no file would be left unformatted. I wonder if there is any tools could help auto formatting after lint.&lt;/li&gt;
&lt;li&gt;When learning typescript, there comes a term &lt;strong&gt;tsc&lt;/strong&gt; means typescript compiler. I am not sure when to use it or do I need to use it manually cos I have built some typescript projects and never use it once. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Photo by &lt;a href="https://www.pexels.com/@shvets-production?utm_content=attributionCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=pexels" rel="noopener noreferrer"&gt;SHVETS&lt;/a&gt; production from &lt;a href="https://www.pexels.com/photo/pile-of-cardboard-boxes-scattered-on-floor-during-relocation-7203788/?utm_content=attributionCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=pexels" rel="noopener noreferrer"&gt;Pexels&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>eslint</category>
      <category>prettier</category>
    </item>
    <item>
      <title>How to make a Noughts and Crosses game in React</title>
      <dc:creator>Sam</dc:creator>
      <pubDate>Wed, 23 Feb 2022 17:40:21 +0000</pubDate>
      <link>https://dev.to/samsonsham/how-to-make-a-noughts-and-crosses-game-in-react-m6e</link>
      <guid>https://dev.to/samsonsham/how-to-make-a-noughts-and-crosses-game-in-react-m6e</guid>
      <description>&lt;p&gt;Photo by Elīna Arāja from Pexels&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fun fact&lt;/strong&gt;: The well known epic mini game "Tic-Tac-Toe" in Britain is called "Noughts and Crosses". While the former one is playing with consonant (T), the later one is playing with the vowel (O).&lt;/p&gt;

&lt;p&gt;I am so excited to have it as my first React.js project. The simple game rule is just good for a junior developer to get familiar with handling logic. Let's take a look at UI design first and then the logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  UI Design
&lt;/h2&gt;

&lt;p&gt;There are 3 main parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Information: Showing who wins. And better show also whose turn.&lt;/li&gt;
&lt;li&gt;Body: The 9 boxes for users to input O or X.&lt;/li&gt;
&lt;li&gt;Button: A "Play Again" button at the end of the game&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the body, I declare a default grid for the 9 boxes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultGrid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then a grid-container is made to contain the 3x3 grid. The gap together with background color do the trick of showing the lines like 井.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.grid-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;15px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#444&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then loop the grid array in JSX.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;grid-container&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;defaultGrid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;boxNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;boxNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;boxNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;boxNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Logic
&lt;/h2&gt;

&lt;p&gt;There should be 3 status for each box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty&lt;/li&gt;
&lt;li&gt;O&lt;/li&gt;
&lt;li&gt;X&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Winning criteria is defined:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;winArrays&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two array is created to contain a list of box number that has been clicked by each side during the game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setNoughtsArr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCrossesArr&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Flow of the program:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clicking one of the 9 buttons&lt;/li&gt;
&lt;li&gt;Insert clicked box number to corresponding array&lt;/li&gt;
&lt;li&gt;Toggle turn&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Winner calculation takes place in &lt;code&gt;useEffect()&lt;/code&gt;, which keep watching at the states of the Noughts Array and Crosses Array.&lt;/p&gt;

&lt;p&gt;I found a function &lt;code&gt;array.every()&lt;/code&gt; in ES6 very helpful for the calculation. On &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every"&gt;MDN website&lt;/a&gt; it has provided an example to check if an array is a subset of another array. So my thought is to check each of the possible win array whether it is a subset of Noughts or Crosses clicked numbers or not. E.g. if the X side has clicked box 1,2,6,9, then &lt;code&gt;crossesArr&lt;/code&gt; would be &lt;code&gt;[1,2,6,9]&lt;/code&gt;. Neither &lt;code&gt;[1, 2, 3]&lt;/code&gt; nor &lt;code&gt;[3, 6, 9]&lt;/code&gt; in &lt;code&gt;winArrays&lt;/code&gt; is a subset of &lt;code&gt;crossesArr&lt;/code&gt; so Crosses has not been qualified to win yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isSubset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;xoArr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;winArr&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;winArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;every&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;xoArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noughtResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winArrays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isSubset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;crossResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winArrays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isSubset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;filter()&lt;/code&gt; will return value that passed &lt;code&gt;isSubset()&lt;/code&gt; checking. So the last thing to do is to check the length of &lt;code&gt;noughtResult&lt;/code&gt; and &lt;code&gt;crossResult&lt;/code&gt; and see which is larger than 0 then that is the winner.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lesson Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Array handling.&lt;/strong&gt; There is quite a number of arrays to handle and calculate. It is also a good exercise for spread operation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functional Programming.&lt;/strong&gt; Tried applying the concepts of functional programming like immutability and separation of data and functions. And I found Single-responsibility principle(SRP) make the testing much easier.&lt;/p&gt;

&lt;p&gt;The code below is showing...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;two higher order functions are created to get correct box status and render a corresponding icon (X/O) by a given box number.&lt;/li&gt;
&lt;li&gt;one higher order function to paint the win icon dynamically.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;getWinBoxStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boxNumber&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;withIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boxNumber&lt;/span&gt;&lt;span class="p"&gt;))}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Grid and Flex in CSS.&lt;/strong&gt; To build a table like layout in a modern way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Typescript.&lt;/strong&gt; This is my first typescript project with ESLint and I am getting mad with so many errors in my code to solve! Time spending on solving typescript errors is probably more than coding the program logic itself. After all, it would still only be a small taste of typescript to me as I didn't do all the variable type and check type.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Pages.&lt;/strong&gt; Setting up GitHub Pages workflow for CI/CD. It does a list of actions like build, test and deploy every time I push the code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Thing to think about
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Extreme Case handling.&lt;/strong&gt; Think about 2 extreme cases: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;All 9 boxes clicked and X win&lt;/li&gt;
&lt;li&gt;All 9 boxes clicked but draw game.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would not be happy if X win but a "Draw Game!" message is shown. In &lt;code&gt;useEffect()&lt;/code&gt; I thought the logic was in sequential order so I tried to put "Handle Draw" after checking winner but it did not work as expected. Below is the code that works fine. I lift "Handle Draw" up to the top so the program can check win before handle draw game as expected. But the order of code goes a bit strange. I'm not sure if anything I missed.&lt;br&gt;
For a quick check, You can try below order of box clicking:&lt;br&gt;
1 2 3 4 5 6 8 9 7 for X win at 9th box.&lt;br&gt;
1 2 3 7 8 9 4 5 6 for draw game.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;winner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setWinner&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle Draw&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;combinedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;combinedArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setWinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Draw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// Check who is eligible to win&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;noughtResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winArrays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isSubset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;crossResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winArrays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isSubset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Setting Winner&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;noughtResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setWinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Noughts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;noughtResult&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;setWinResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;crossResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;setWinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Crosses&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;crossResult&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nx"&gt;setWinResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Nought and Crosses:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/samsonsham/noughts-and-crosses"&gt;Github&lt;/a&gt;&lt;br&gt;
&lt;a href="https://samsonsham.github.io/noughts-and-crosses/"&gt;Live site&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;2022-02-27 Update:&lt;/strong&gt;&lt;br&gt;
I added a variable &lt;code&gt;thisWinner&lt;/code&gt; for "Handle Draw" to refer to. So that the flow would look better and make more sense.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check who is eligible to win&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;noughtResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winArrays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isSubset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;crossResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;[][]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;winArrays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isSubset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;winArray&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// Setting Winner&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;thisWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;noughtResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;thisWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Noughts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;noughtResult&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="nx"&gt;setWinResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;crossResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;thisWinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Crosses&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;crossResult&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="nx"&gt;setWinResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;setWinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;thisWinner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Handle Draw&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;combinedArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;thisWinner&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;combinedArr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;setWinner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Draw`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;noughtsArr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;crossesArr&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>tictactoe</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Becoming A Front End Developer</title>
      <dc:creator>Sam</dc:creator>
      <pubDate>Thu, 17 Feb 2022 00:41:47 +0000</pubDate>
      <link>https://dev.to/samsonsham/becoming-a-front-end-developer-4716</link>
      <guid>https://dev.to/samsonsham/becoming-a-front-end-developer-4716</guid>
      <description>&lt;p&gt;&lt;strong&gt;A whole new world?&lt;/strong&gt;&lt;br&gt;
If you are fond of travelling, you would be quite upset these years due to the pandemic. Meanwhile, 2022 is the year I move from Hong Kong to UK. Despite how exciting I would be since there would be lots of things to explore, it is also challenging to settle down in a new place. After all, it would also be a good time for me to re-think my career at the moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First things first, HTML and CSS.&lt;/strong&gt;&lt;br&gt;
Although IT was not my first choice in the university, I got a related bachelor degree more than 10 years ago. At the beginning of my first job, I don't even know much about HTML and CSS. But I got a task to revamp the school website which is full of table layout, embedded javascript and Adobe Flash. I found it is the part of the job I mostly enjoy among all the tasks from adhoc hardware support to movie editing.&lt;/p&gt;

&lt;p&gt;I remember there was a website called CSS Zen Garden. I was caught by the beauty of the tidiness and simplicity of the layout, and the possibility of CSS. So I learnt HTML and CSS at that time as well as some concepts of separation of HTML, CSS and JS. And I dreamed of building a successful website. After two years, I was able to find a Java related job in a government department as an IBM Web Sphere portal support staff.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here comes the Java&lt;/strong&gt;&lt;br&gt;
Again, I don't know any of Java. Not to mention J2EE, and many of enterprise level applications. But I have was again caught by the power of JSP and servlet. So I learnt Java SE and got a SCJP. Later on, I took a J2EE course to learn those MVC frameworks like Struts, Spring and JSF. &lt;/p&gt;

&lt;p&gt;After some years, I was able to find a Java developer job in a QUANGO. This is the time I feel like I am an IT professional finally. As the team was running Scrum model, I have to keep tracking on my tasks on Kanban board and attend stand up meeting everyday. In fact I feel like if I want to build a professional full functions website, I have to be a full stack developer, or even more of a back-end developer to deal with servlet and EJB logics. I had to learn gangs of four design pattern, and ACID principle of database as well.&lt;/p&gt;

&lt;p&gt;One thing very basically make me not feeling confidence of using Java is my struggling to "Object Oriented". When I practice myself, I often think the object I have designed is not good enough. And falling in the loop of abstraction to make the tight-coupling loose. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Taking a breath&lt;/strong&gt;&lt;br&gt;
A year later, my former supervisor ask me to help with retirement of the Portal. I want to take a breath so I came back, regardless there is not much coding in the system support role. Until last year, I feel a bit lost and in a bottleneck of my career. Plus something unpleasant happened in my home country, so I decided to go to UK.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leaving the old world&lt;/strong&gt;&lt;br&gt;
I would like to do any part-time job to earn a living. But for full time job, this time, I don't want to rush for a job only because I want a job. As my skills are almost outdated (I am a SCJP6 holder), I have to catch up with the latest skill. And I found Spring is in my pocket, so I spend some time to catch up with Spring Boot and hoping to continue my Java career, and there come a word micro service. From my very rough understanding, it would be like they concentrate on building middleware like Restful API. That means Java has already fade out from the front end. No more JSP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yes, a whole new world!&lt;/strong&gt;&lt;br&gt;
It's good to know what is outdated and what is still alive. There is a period of time last month I keep on googling "Is XXX dead?" (e.g. is JSP dead, is jQuery dead, is CSS dead).  For Angular and React, I know the name of these hot front-end frameworks for long time but just didn't try it (as my main is Java). So I would like to pick one to start. I made a decision after doing a search in Stack Overflow Trend. Last month I started to learn React and I was deeply attracted! Despite React has been released for years, I don't know front-end framework like this could change the game totally. And there seems no more jQuery, which has been so hot before. Though there are lots of concepts like declarative VS imperative, Virtual Dom, Component base, JSX...I don't have any feeling of overwhelming like I learn Java before. Another thing that I am amazed and feel thankful is functional programming, which save me from OO! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's never too late to learn new thing.&lt;/strong&gt;&lt;br&gt;
Now I have already launch my portfolio website with Next.js, a React framework (It is interesting to me that very often there is a framework on top of a framework.) which seems concerning the issues like Server Side Rendering (SSR) ,Static Site Generation (SSG) and SEO. I am so exciting that I coded my personal website.&lt;/p&gt;

&lt;p&gt;I also find lots of UI Libraries like MUI, Chakra, Tailwind...oh...when I mention Tailwind, that would lead to a question, how should I do the styling stuff now, and where should I put CSS to. Are those CSS pre-processor like SASS and LESS dead? Should I use Tailwind CSS, Styled Components or Styled props of emotion? While I might finally pick one, I would like to try them one by one in my own projects.&lt;/p&gt;

&lt;p&gt;I feel refreshed and feeling more comfortable for frontend development with updated tech.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Next?&lt;/strong&gt;&lt;br&gt;
Typescript. My first project is Tic-tac-toe (knowns as Noughts and Crosses in UK). And I would take this project as my typescript exercise.&lt;/p&gt;

&lt;p&gt;Happy hacking!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>javascript</category>
      <category>java</category>
    </item>
  </channel>
</rss>
