{"id":28315850,"url":"https://github.com/drborges/react-by-example-template","last_synced_at":"2025-08-26T00:15:28.989Z","repository":{"id":141687684,"uuid":"332862263","full_name":"drborges/react-by-example-template","owner":"drborges","description":"Created with CodeSandbox","archived":false,"fork":false,"pushed_at":"2021-01-27T13:34:15.000Z","size":27,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-07T11:11:13.361Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/github/drborges/react-by-example-template","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drborges.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2021-01-25T19:38:29.000Z","updated_at":"2021-01-27T13:34:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"7bf74154-a44f-470e-b8ac-c41fda2db305","html_url":"https://github.com/drborges/react-by-example-template","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/drborges/react-by-example-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drborges%2Freact-by-example-template","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drborges%2Freact-by-example-template/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drborges%2Freact-by-example-template/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drborges%2Freact-by-example-template/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drborges","download_url":"https://codeload.github.com/drborges/react-by-example-template/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drborges%2Freact-by-example-template/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272150638,"owners_count":24882203,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-25T02:00:12.092Z","response_time":1107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-25T01:12:45.967Z","updated_at":"2025-08-26T00:15:28.982Z","avatar_url":"https://github.com/drborges.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React by Example: Tic-tac-toe Game\n\nLearn React by doing it.\n\nThis repo provides the reference code used by the short tutorial below. [Check out this Codesandbox](https://codesandbox.io/s/react-tic-tac-toe-egbnq?file=/src/index.jsx) to see the game in action along with its source code.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"50%\" alt=\"tic tac toe demo\" src=\"docs/images/tic-tac-toe-demo.gif\" /\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n- [What's React](#whats-react)\n- [What's a React Component?](#whats-a-react-component)\n  - [Stateless Components](#stateful-components)\n    - [Basic Component Structure](#basic-component-structure)\n    - [Children Elements](#children-elements)\n  - [Styling Components](#styling-components)\n  - [Thinking in React](#thinking-in-react)\n  - [Stateful Components](#stateful-components)\n  - [Custom Hooks: Reusable Application Logic](#custom-hooks-reusable-application-logic)\n  - [Component Lifecycle](#component-lifecycle)\n    - [The Mount Phase](#the-mount-phase)\n    - [The Update Phase](#the-update-phase)\n    - [The Unmount Phase](#the-unmount-phase)\n    - [Hooking Into the Lifecycle](#hooking-into-the-lifecycle)\n  - [Accessing Application Data Through Context]()\n  - [Optimizations](#optimizations)\n    - [Memoizing Callbacks](#memoizing-callbacks)\n    - [Memoizing Expensive Computations](#memoizing-expensive-computations)\n    - [Preventing Unnecessary Rendering](#prevent-unnecessary-rendering-cycles)\n  - [Resources](#resources)\n\n## What's React?\n\n[React](https://reactjs.org/) is A JavaScript library for building user interfaces, it's `declarative` and `component` based.\n\nDevelopers can simply describe what the UI should look like by creating and composing components together, and React takes care of rendering these components to the target platform (DOM, iOS, Android, Shell, etc...) in the most efficent way possible.\n\n## What's a React Component?\n\n1. The basic building block in the React ecosystem;\n2. It's simply a JS function (for the most part 😅);\n3. Can optionally receive data via its first argument, known as `props`;\n4. Return markup code that looks a lot like HTML, known as `JSX`;\n5. Can be stateless or statefull;\n\n## Stateless Components\n\nStateless components are the simplest form of a React component.They can optionally receive data via `props` and returns JSX code that describes the UI requirements of the component. They do not hold internal state, therefore, stateless components.\n\nThis type of component can be treated as a pure function, where given the same input, e.g. `props` we always get the same `JSX` output.\n\n### Basic Component Structure\n\n_/src/index.js_\n\n```jsx\nimport ReactDOM from \"react-dom\"\n\nfunction Greeting(props) {\n  return \u003ch1\u003eHello {props.name}!\u003c/h1\u003e\n}\n\nReactDOM.render(\u003cGreeting name=\"Create 2021.1\" /\u003e, document.getElementById(\"root\"))\n```\n\nAs it may already be obivious, the `name` attribute above is accessible within the component's function definition through its `props` argument. This usage will render the following to the DOM:\n\n```html\n\u003ch1\u003eHello Create 2021.1!\u003c/h1\u003e\n```\n\n### Children Elements\n\nReact components can also wrap children elements, which are made accessible via the `props` argument, just like any other regular prop passed to the component. Children elements can be **any** type of React expression, that being built-in tags such as `div` and `p`, a text node, or other components.\n\nLet's imagine a `Card` component that can be used as a container to hold any number of children elements. This is what it could look like:\n\n_/src/index.js_\n\n```jsx\nimport ReactDOM from \"react-dom\"\n\nfunction Card(props) {\n  return (\n    \u003cdiv\u003e{props.children}\u003c/div\u003e\n  )\n}\n\nconst app = (\n  \u003cCard\u003e\n    \u003cGreeting name=\"Alice\" /\u003e\n    {\"Look! I'm a text node!}\n    \u003cGreeting name=\"Bob\" /\u003e\n    \u003cp\u003enow with built-in tags...\u003c/p\u003e\n  \u003c/Card\u003e\n)\n\nReactDOM.render(\n  app,\n  document.getElementById(\"root\"),\n)\n```\n\n## Styling Components\n\nReact Components [can be styled in various ways](https://reactjs.org/docs/faq-styling.html), here're the three most common ones:\n\n1. Declarativelly, with regular CSS by passing class names to the component via the `className` prop;\n2. Programatically, by passing a JS object containing CSS properties to thee component via the `style`props;\n3. Using [CSS Modules](https://css-tricks.com/css-modules-part-1-need/) to provide CSS code scoped to your component, preventing issues like CSS leaking throughout the app;\n\nLet's see how we'd style our `Greeting` component using all three strategies:\n\n\u003cdetails\u003e\u003csummary\u003ePlain CSS\u003c/summary\u003e\n\n_/src/styles.css_\n\n```css\n.greeting {\n  color: green;\n}\n```\n\n_/src/index.js_\n\n```jsx\nimport ReactDOM from \"react-dom\"\n\nimport \"./styles.css\"\n\nfunction Greeting(props) {\n  return \u003ch1 className=\"greeting\"\u003eHello {props.name}!\u003c/h1\u003e\n}\n\nReactDOM.render(\u003cGreeting name=\"Create 2021.1\" /\u003e, document.getElementById(\"root\"))\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eStyle Prop\u003c/summary\u003e\n\n_/src/index.js_\n\n```jsx\nimport ReactDOM from \"react-dom\"\n\nfunction Greeting(props) {\n  const css = { color: \"green\" }\n  return \u003ch1 style={css}\u003eHello {props.name}!\u003c/h1\u003e\n}\n\nReactDOM.render(\u003cGreeting name=\"Create 2021.1\" /\u003e, document.getElementById(\"root\"))\n```\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\u003csummary\u003eCSS Modules\u003c/summary\u003e\n\n_/src/styles.module.css_\n\n```css\n.greeting {\n  color: green;\n}\n```\n\n_/src/index.js_\n\n```jsx\nimport ReactDOM from \"react-dom\"\n\nimport styles from \"./styles.module.css\"\n\nfunction Greeting(props) {\n  return \u003ch1 className={styles.greeting}\u003eHello {props.name}!\u003c/h1\u003e\n}\n\nReactDOM.render(\u003cGreeting name=\"Create 2021.1\" /\u003e, document.getElementById(\"root\"))\n```\n\n\u003c/details\u003e\n\n## Thinking in React\n\nWhen building apps with React (or any component driven lib for that matter), it is often useful (and a good practice) to break down the UI into simpler abstractions, where each abstraction can be implemented by its own React component and later composed together to form the final result. Think LEGO bricks 👌🏾\n\nHere's one way to break down the Tic-Tac-Toe app into smaller building blocks:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg width=\"50%\" alt=\"Thinking in React\" src=\"docs/images/app-thinking-in-react.png\" /\u003e\n\u003c/p\u003e\n\n1. `Game` component: It's the root component of our app, the entrypoint. This is going to be our stateful component, responsible for holding the game state;\n2. `Card` component, implements the card container;\n3. `Text` component, implements an abstraction of text elements so we can encapsulate app specific styles and reuse throughout the app;\n4. `Board` component, implements the Tic-Tac-Toe board;\n5. `Cell` component, implements the board cells as buttons that the user can click on in order to make a move;\n6. `Button` component, very much like the `Text` component, this one will encapsulate app specific styles and so it can be reused throughout the app;\n\nAs you may have noticed, the structure of a React app, very much like the HTML DOM, is a tree. Here's what our Components Tree will look like:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Components Tree\" src=\"docs/images/tic-tac-toe-components-tree.png\" /\u003e\n\u003c/p\u003e\n\nThe [Thinking in React article](https://reactjs.org/docs/thinking-in-react.html) covers this topic in more detail, and it's a must read resource for anyone working with this type of UI development paradigm.\n\n## Stateful Components\n\nAs opposed to steteless components, stateful components do hold internal state that can be combined with its `props` in order to drive the construction of the JSX markup, e.g., conditionally render elements to the screen, toggle css classes on elements as a result of user interaction, hold user input, etc...\n\nInternal state can be created using the `useState` React hook function, and this is one of the many built-in [hooks](https://reactjs.org/docs/hooks-intro.html) provided by React that we'll rely on in order to control our components' internal state, create reusable stateful logic, and hook into the component lifecycle. Hooks simply put, are:\n\n1. Functions whose names start with `use`;\n2. May call other hooks;\n3. Can't be conditionally executed, nor can't be called within callbacks. Learn more about [Rules of Hooks heres](https://reactjs.org/docs/hooks-rules.html)\n\nLet's build a `Counter` app to see this in action!\n\n_/src/index.js_\n\n```jsx\nimport { useState } from \"react\"\nimport ReactDOM from \"react-dom\"\n\nfunction Counter({ initialCount }) {\n  const [count, setCount] = useState(initialCount)\n  const decrement = () =\u003e setCount((currentCount) =\u003e currentCount - 1)\n  const increment = () =\u003e setCount((currentCount) =\u003e currentCount + 1)\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={decrement}\u003e-1\u003c/button\u003e\n      {count}\n      \u003cbutton onClick={increment}\u003e+1\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n\nReactDOM.render(\u003cCounter initialCount={0} /\u003e, document.getElementById(\"root\"))\n```\n\nThe `useState` hook takes as argument the initial value of the state being created and returns an array with two items. The first item is the current value of the state, and the second, an update function that can be used to update the state with new values causing the React component to re-render.\n\nEvery time the `+1` button is clicked, the current cound is incremented by one and the React component is re-rendered so the new value is displayed. Similarly, clicking the `-1` button will cause the same process to take place, but decrementing the sate by one instead.\n\nWith that, we have our first statefull React component 🎉.\n\n## Custom Hooks: Reusable Application Logic\n\nOften times application logic grows too much that keeping all of it within your component starts to hurt code readability, making it a real challenge to maintain the codebase. Thankfully, React allows us to create custom hooks, which is a great way to encapsulate code and provide reusable application logic.\n\nTaking our Counter app as an example, we can extract the stateful logic into a custom hook and reuse it in the React component:\n\n```jsx\nimport ReactDOM from \"react-dom\"\nimport { useState } from \"react\"\n\nfunction useCounter(initialCount) {\n  const [count, setCount] = useState(initialCount)\n  const decrement = () =\u003e setCount((currentCount) =\u003e currentCount - 1)\n  const increment = () =\u003e setCount((currentCount) =\u003e currentCount + 1)\n\n  return {\n    count,\n    decrement,\n    increment,\n  }\n}\n\nfunction Counter({ initialCount }) {\n  const { count, decrement, increment } = useCounter(initialCount)\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={decrement}\u003e-1\u003c/button\u003e\n      {count}\n      \u003cbutton onClick={increment}\u003e+1\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n\nReactDOM.render(\u003cCounter initialCount={0} /\u003e, document.getElementById(\"root\"))\n```\n\n## Component Lifecycle\n\nReact Components usually have the following lifecycle:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"lifecycle\" src=\"docs/images/lifecycle-phases.png\" /\u003e\n\u003c/p\u003e\n\nLet's run our `Counter` app through this diagram and see how that progresses:\n\n### The `Mount` Phase\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"mount phase\" src=\"docs/images/mount-phase.png\" /\u003e\n\u003c/p\u003e\n\nThis is the first step in the lifecycle, and it happens as soon as the component is rendered to the DOM (e.g. mounted) via `ReactDOM.render`\n\n### The `Update` Phase\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"update phase\" src=\"docs/images/update-phase.png\" /\u003e\n\u003c/p\u003e\n\nExecuted whenever the component state is updated, in our case, whenever we click the `+1` or `-1` buttons. This phase can also run in a stateless child component if a stateful parent component updates, causing the child to re-render as well.\n\n### The `Unmount` Phase\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"unmount phase\" src=\"docs/images/unmount-phase.png\" /\u003e\n\u003c/p\u003e\n\nExecuted when the component is removed from the DOM. During this phase, we can run clean up code to avoid memory leaking, things like canceling timers, unsubscribing from PubSub channels, etc...\n\n### Hooking Into the Lifecycle\n\nReact allows us to write code that is bound to specific phases of the component's lifecycle via the [useEffect Hook](https://reactjs.org/docs/hooks-effect.html). This kind of code is also know as side-effects. Some of the use cases for this type of hook are:\n\n1. Fetch data asynchronously as soon as the component is mounted;\n1. Perform work as a result of some specific state change;\n1. Initiate a timer when the component is mounted;\n1. Subscribe and unsubscribe to pubsub events when the component is monted and unmounted respectively;\n\nLet's take the `Counter` app again as reference, and imagine that a hypothetical client asked you to implement a timer. This timer should simply show the user how many seconds have passed since the timer started. Luckly, we can reuse the `useCounter` hook implemented in the previous section to provide the application logic that will be used by a side-effect that runs every second. Here's a first attempt at implementing the `Timer` component:\n\n```jsx\nimport ReactDOM from \"react-dom\"\nimport { useEffect, useState } from \"react\"\n\nfunction useCounter(initialCount) {\n  const [count, setCount] = useState(initialCount)\n  const decrement = () =\u003e setCount((currentCount) =\u003e currentCount - 1)\n  const increment = () =\u003e setCount((currentCount) =\u003e currentCount + 1)\n\n  return {\n    count,\n    decrement,\n    increment,\n  }\n}\n\nfunction Timer({ initialCount }) {\n  const { count, increment } = useCounter(initialCount)\n\n  useEffect(() =\u003e {\n    setInterval(increment, 1000)\n  })\n\n  return \u003cdiv\u003e{count} seconds have passed.\u003c/div\u003e\n}\n\nReactDOM.render(\u003cTimer initialCount={0} /\u003e, document.getElementById(\"root\"))\n```\n\nIf we run the code we'll see that the timer does not behave as expected, and instead, the count will increases exponentially every second rather than one unit at a time. That's because `useEffect` runs every time the `Timer` component renders, creating a new instance of timer every second, each incrementing the count by one, every second. To prevent this behavior, we need a [cleanup phase](https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup) to take place and cancel the current timer before creating a new one. We can achieve that by returning a cleanup function from the effect that performs the cancellation of the timer:\n\n```jsx\nimport ReactDOM from \"react-dom\"\nimport { useEffect, useState } from \"react\"\n\nfunction useCounter(initialCount) {\n  const [count, setCount] = useState(initialCount)\n  const decrement = () =\u003e setCount((currentCount) =\u003e currentCount - 1)\n  const increment = () =\u003e setCount((currentCount) =\u003e currentCount + 1)\n\n  return {\n    count,\n    decrement,\n    increment,\n  }\n}\n\nfunction Timer({ initialCount }) {\n  const { count, increment } = useCounter(initialCount)\n\n  useEffect(() =\u003e {\n    const timer = setInterval(increment, 1000)\n    return () =\u003e clearInterval(timer)\n  })\n\n  return \u003cdiv\u003e{count} seconds have passed.\u003c/div\u003e\n}\n\nReactDOM.render(\u003cTimer initialCount={0} /\u003e, document.getElementById(\"root\"))\n```\n\nThis works great for our purpose! However, the side-effect code still runs every second. We can optimize that behavior so that the side-effect runs only when absolutely needed. See [Memoizing Callbacks](#memoizing-callbacks) to learn more about this optimization.\n\n## Accessing Application Data Through Context\n\nuseContext: TODO\n\n## Optimizations\n\n### Memoizing Callbacks\n\nThis version looks much better! However, eventhough the timer cleans after itself, it creates a new timer every second! It would be ideal if only one timer gets created for the duration of the component's lifespan. Well, `useEffect` to the rescue! We can pass as the second argument, a list of dependencies that will instruct React to run the side-effect when the component is mounted as well as whenever any of these dependencies change. In this case, the only dependency that the side-effect code has is the `increment` function:\n\n```jsx\nuseEffect(() =\u003e {\n  const timer = setInterval(increment, 1000)\n  return () =\u003e clearInterval(timer)\n}, [increment])\n```\n\nThere's a catch though, `useCounter` returns a new `increment` function whenever it runs, which will cause the side-effect to run every second just like before. To work around this, we can rely on another built-in hook, [`useCallback`](https://reactjs.org/docs/hooks-reference.html#usecallback), to \"cache\" the `increment` function, so the same instance is returned across update cycles, and only returning a new instance, if some dependency is updated (sounds familiar?). Here's what the more optimized code will look like:\n\n```jsx\nimport ReactDOM from \"react-dom\"\nimport { useCallback, useEffect, useState } from \"react\"\n\nfunction useCounter(initialCount) {\n  const [count, setCount] = useState(initialCount)\n  const decrement = () =\u003e setCount((currentCount) =\u003e currentCount - 1)\n  const increment = useCallback(() =\u003e setCount((currentCount) =\u003e currentCount + 1), [setCount])\n\n  return {\n    count,\n    decrement,\n    increment,\n  }\n}\n\nfunction Timer({ initialCount }) {\n  const { count, increment } = useCounter(initialCount)\n\n  useEffect(() =\u003e {\n    const timer = setInterval(increment, 1000)\n    console.log(\"Running Side-Effect only once...\")\n    return () =\u003e clearInterval(timer)\n  }, [increment])\n\n  return \u003cdiv\u003e{count} seconds have passed.\u003c/div\u003e\n}\n\nReactDOM.render(\u003cTimer initialCount={0} /\u003e, document.getElementById(\"root\"))\n```\n\nTwo things happened here:\n\n1. We've imported `useCallback` from the `react` package;\n1. We've wrapped the `increment` function definition with `useCallback`, passing `setCount` as its only dependency.\n\nThese changes ensure that the side-effect code in the `Timer` component only executes when the `increment` function changes and since that in our example, `setCount` does not change across updates, the side-effect code will run only once.\n\n### Memoizing Expensive Computations\n\nuseMemo: TODO\n\n### Preventing Unnecessary Rendering\n\nReact.memo: TODO\n\n## Resources\n\n- [React Docs](https://reactjs.org/docs/getting-started.html)\n- [Hooks Docs](https://reactjs.org/docs/hooks-intro.html)\n- [Thinking in React](https://reactjs.org/docs/thinking-in-react.html)\n- [The Beginner's Guide to React](https://egghead.io/courses/the-beginner-s-guide-to-react)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrborges%2Freact-by-example-template","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrborges%2Freact-by-example-template","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrborges%2Freact-by-example-template/lists"}