{"id":21936113,"url":"https://github.com/learnweb3dao/just-enough-react-and-nextjs","last_synced_at":"2025-03-22T14:16:31.929Z","repository":{"id":40259591,"uuid":"486904935","full_name":"LearnWeb3DAO/Just-Enough-React-And-Nextjs","owner":"LearnWeb3DAO","description":null,"archived":false,"fork":false,"pushed_at":"2022-09-04T22:22:30.000Z","size":125,"stargazers_count":3,"open_issues_count":0,"forks_count":6,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-01-27T13:25:08.048Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"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/LearnWeb3DAO.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}},"created_at":"2022-04-29T09:00:30.000Z","updated_at":"2022-06-28T04:03:08.000Z","dependencies_parsed_at":"2022-08-30T15:21:17.824Z","dependency_job_id":null,"html_url":"https://github.com/LearnWeb3DAO/Just-Enough-React-And-Nextjs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FJust-Enough-React-And-Nextjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FJust-Enough-React-And-Nextjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FJust-Enough-React-And-Nextjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LearnWeb3DAO%2FJust-Enough-React-And-Nextjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LearnWeb3DAO","download_url":"https://codeload.github.com/LearnWeb3DAO/Just-Enough-React-And-Nextjs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244966524,"owners_count":20539797,"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","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":"2024-11-29T01:13:15.543Z","updated_at":"2025-03-22T14:16:31.907Z","avatar_url":"https://github.com/LearnWeb3DAO.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Just Enough React (and Next.js)\n\nIn the Freshman Track, we built a very simple dApp that used HTML, CSS, and some Javascript. In the real world, however, these type of 'vanilla' website implementations are a thing of the past. \n\nToday, we use web frameworks to simplify the web development process. Is it simpler though? Depends on whose perspective you're looking from. If you're just starting out and have never done this before, it may take some time till you understand all the necessary concepts. But, in the long run, you will thank yourself and be happy that you took the time to learn it.\n\nThe biggest and most common web frameworks used today are:\n- [React](https://reactjs.org)\n- [Angular](https://angular.io)\n- [Vue](https://vuejs.org)\n\nWhile they each have their own pros and cons, React has by far taken the web development world by storm. The same is true in the Web3 space, where React is the most commonly used web framework for building dApps. Throughout the Sophomore track, and all later tracks as well, we will be using a lot of React, so think of this level as a React crash course which will teach you *just enough* to get started. This is not meant to be a replacement for learning React on platforms that focus on teaching Web2, but is to be used as a guide to understand just how much is necessary to get started so you don't get stuck in tutorial hell. 😅\n\n\u003e Actually, we will be using Next.js - which is an extension of React itself - but more on that later. Let's learn some React first.\n\n## WTF is React?\nReact is a web framework that makes it easy to build and reason about the 'view' of your web app. The 'view' is what is displayed on the screen, how it changes, how it updates, etc. React essentially just gives you a template language, and you can **create Javascript functions that return HTML.**\n\nNormal Javascript functions return Javascript-esque things - strings, numbers, booleans, objects, etc. React basically combined Javascript and HTML to produce a language they call **JSX**. In JSX, Javascript-like functions return HTML instead of regular Javascript things. That's basically it.\n\n\u003cQuiz questionId=\"8c7c3dd2-2297-4cdb-933b-93c38fb64ecd\" /\u003e\n\nThe combination of Javascript functions that return HTML are called **Components**. Components are written in JSX. Though seemingly awkward at first, they are actually quite easy to work with once you get used to it.\n\nHere's an example of a simple component:\n\n```jsx\nfunction ShoppingList() {\n    return (\n      \u003cdiv className=\"shopping-list\"\u003e\n        \u003ch1\u003eShopping List\u003c/h1\u003e\n        \u003cul\u003e\n          \u003cli\u003eApples\u003c/li\u003e\n          \u003cli\u003eBananas\u003c/li\u003e\n          \u003cli\u003eGrapes\u003c/li\u003e\n        \u003c/ul\u003e\n      \u003c/div\u003e\n    );\n}\n```\n\n\u003cCodeSandbox title=\"icy-water-xrm2ch\" /\u003e\n\nGreat, but this isn't much different from HTML. But what if you wanted to render a list of items based on an array?\n\n```jsx\nfunction ShoppingList() {\n    const items = [\"Apples\", \"Bananas\", \"Grapes\"]\n    \n    return (\n      \u003cdiv className=\"shopping-list\"\u003e\n        \u003ch1\u003eShopping List\u003c/h1\u003e\n        \u003cul\u003e\n            {items.map((item, index) =\u003e \u003cli key={index}\u003e{item}\u003c/li\u003e)}\n        \u003c/ul\u003e\n      \u003c/div\u003e\n    );\n}\n```\n\n\u003cCodeSandbox title=\"confident-tesla-5l3k1t\" /\u003e\n\nWow, look at that! We just used Javascript inside HTML. In JSX, you can write Javascript inside HTML by wrapping the JS code in curly braces `{` and `}`. Actually though, if you think about this a little more, you will realize what is happening. `.map()` is a Javascript function, which loops over an array and returns something for each item. In this case, it is looping over the `items` array and returning an `li` element, that has the value of the Javascript variable `item` within it, which is HTML. Get it? 🤔\n\nInside our component, we basically embedded another component. The map function is a JS function that returns HTML. It is a component. Even though it is not explicitly defined as a top level function, it is still a component. \n\n**Embedding components inside other components is the power of React.** This is called **Composition**. We are composing together multiple Javascript functions that return HTML, and building up a single combined HTML document from it that will be displayed on the web app.\n\n\u003cQuiz questionId=\"4ac6b0df-759d-4f46-a67b-175c55d75aa6\" /\u003e\n\n## Data Passing between Components\n\nComponents are not very useful if they are just static. Sure, looping over arrays and things are fine, but most web apps today are not static documents. Most web apps today will dynamically fetch data from some sort of server, database, or blockchain. This means the same component will often times be required to display different data.\n\nThe main use case of having components is being able to write code that is reusable and can, within it, contain different information without rewriting the entire code again.\n\nLet's take a look at an example. Which of these two codes is more readable?\n\n```html\n\u003cdiv class=\"cards\"\u003e\n    \u003cdiv class=\"card\"\u003e\n      \u003cimg src=\"img_avatar.png\" alt=\"Avatar\"\u003e\n      \u003cdiv class=\"container\"\u003e\n        \u003ch4\u003e\u003cb\u003eAlice\u003c/b\u003e\u003c/h4\u003e\n        \u003cp\u003eFrontend Developer\u003c/p\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e \n\n    \u003cdiv class=\"card\"\u003e\n      \u003cimg src=\"img_avatar.png\" alt=\"Avatar\"\u003e\n      \u003cdiv class=\"container\"\u003e\n        \u003ch4\u003e\u003cb\u003eBob\u003c/b\u003e\u003c/h4\u003e\n        \u003cp\u003eBackend Developer\u003c/p\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e \n\n    \u003cdiv class=\"card\"\u003e\n      \u003cimg src=\"img_avatar.png\" alt=\"Avatar\"\u003e\n      \u003cdiv class=\"container\"\u003e\n        \u003ch4\u003e\u003cb\u003eCharlie\u003c/b\u003e\u003c/h4\u003e\n        \u003cp\u003eFull Stack Developer\u003c/p\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\n```jsx\nfunction Cards() {\n    return (\n        \u003cdiv className=\"cards\"\u003e\n            \u003c!--Data is passed to children through HTML attributes--\u003e\n            \u003cCard name=\"Alice\" job=\"Frontend Developer\" /\u003e\n            \u003cCard name=\"Bob\" job=\"Backend Developer\" /\u003e\n            \u003cCard name=\"Charlie\" job=\"Full Stack Developer\" /\u003e\n        \u003c/div\u003e\n    )\n}\n\n// Card receives an object as an argument\n// We can destructure the object to get specific variables\n// from inside the object - name and job\nfunction Card({name, job}) {\n    return (\n        \u003cdiv className=\"card\"\u003e\n            \u003cimg src=\"img_avatar.png\" /\u003e\n            \u003cdiv className=\"container\"\u003e\n                \u003ch4\u003e\u003cb\u003e{name}\u003c/b\u003e\u003c/h4\u003e\n                \u003cp\u003e{job}\u003c/p\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cCodeSandbox title=\"zealous-carson-44om2s\" /\u003e\n\nThe plain HTML example reused the same code three times, even though the only thing that actually changed was just the name of the person and their job title. \n\nIn JSX, we can abstract away each `Card` as a component, which takes certain data from it's parent component (in this case, `Cards`). parent component passes data to the child through HTML-like attributes (`name=\"Alice\"`), and the child accesses their values like a JS function receiving a JS object as an argument. The `Card` component can then return HTML with variable data inside it depending on what it received from the parent.\n\n\u003cQuiz questionId=\"febb9535-244f-4836-abd2-8aa06351f8a2\" /\u003e\n\nThis code is much more easily reusable and extendable. Want to slightly change how all the cards look? Just modify a single component! Not all the copy-pasted HTML.\n\n\u003cQuiz questionId=\"e7dfcdde-d2e1-47ec-947a-1a134ce8378f\" /\u003e\n\n## Interactive Components\nAlright, so we can now pass data between components. That is all good, but we haven't yet added interactivity. Things like being able to run some code when a button is clicked, or when text is typed into an input box, etc.\n\nThankfully, in Javascript, functions can contain functions within them. For example,\n\n```js\nfunction someFunc() {\n    \n    function otherFunc() {\n        console.log(\"Hello!\")\n    }\n    \n    otherFunc();\n}\n\nsomeFunc(); // will print \"Hello!\"\n\notherFunc(); // will throw an error! undefined here\n```\n\n`otherFunc` is only available for use inside the `someFunc` itself. This is a rarely used feature in regular Javascript, but is very heavily used when working with React. Let's see why with an example.\n\n\u003cQuiz questionId=\"bda73acd-8b42-4918-a2d8-e3a1b5596f3e\" /\u003e\n\n```jsx\nfunction Button() {\n    \n    function handleClick() {\n        console.log(\"Hello\")\n    }\n    \n    return (\n        \u003cbutton \n            className=\"button\" \n            onClick={handleClick}\u003e\n            Click Me!\n        \u003c/button\u003e\n    )\n    \n}\n```\n\n\u003cCodeSandbox title=\"quizzical-sammet-59fi5i\" /\u003e\n\nWe have a JSX Function called `Button`. Within this function, we have another function called `handleClick`. In the HTML `\u003cbutton\u003e` tag, we specify `onClick={handleClick}` so when the button is clicked, the `handleClick` function is called. This function is only available inside the `Button` component. Clicking the button on the web app will print `Hello` in the browser console. This is how we build interactive websites with React!\n\nThat example is still fairly simple, because `handleClick` takes no arguments. What if we want to print text in the console as the user is typing into an input box? How do we pass the text to the function?\n\nHere's how.\n\n```jsx\nfunction PrintTypedText() {\n    \n    function handleOnChange(text) {\n        console.log(text);\n    }\n    \n    return (\n        \u003cinput \n            type=\"text\" \n            onChange={(e) =\u003e handleOnChange(e.target.value)}\n        /\u003e\n    )\n}\n```\n\n\u003cCodeSandbox title=\"mutable-feather-el4sbe\" /\u003e\n\nThe HTML `input` element provides a handy event listener - `onChange` - that is triggered every time the text in that input box changes (typing a new character, deleting a character, etc.). \n\nAlong with triggering a function though, it also passes along the HTML element that changed (referred to as `e` here). We can then take the HTML element `e` and extract the text using `e.target.value` and pass it as an argument to `handleOnChange` which will log the text to the browser console.\n\nDifferent HTML elements have different event handlers - `onChange` and `onClick` are two examples, but there are many more! You can find a list of all HTML events [here](https://www.w3schools.com/jsref/dom_obj_event.asp).\n\nBy combining HTML events with function handlers, we can do all sorts of cool things! Load data from a server, send data to a server, update our view, etc.\n\n## React Hooks - useState and useEffect\nAlright, we have gone over Composition, Data Passing, and Interactivity. But, our apps are still quite dumb. Interactivity will allow you to run some code on button clicks etc. but what if you want to update some variables?\n\nUnfortunately, the following **does not** work\n\n```jsx\nfunction DoesNotWork() {\n    let myNumber = 0;\n    \n    function increment() {\n        myNumber++;\n    }\n    \n    return (\n        \u003cdiv\u003e\n            \u003cp\u003e{myNumber}\u003c/p\u003e\n            \u003cbutton onClick={increment}\u003eIncrement!\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cCodeSandbox title=\"romantic-euclid-44hh8x\" /\u003e\n\nNo matter how many times you click the `Increment` button, the displayed number on the screen will be stuck at `0`. This is because when you update regular variables like `myNumber` from within a React component, even though the value is updated, React does not actually re-render the view of the web app. It does not automatically update the HTML view of the page.\n\n\u003cQuiz questionId=\"4665f339-24c6-41ea-8e93-9cf8de501f5b\" /\u003e\n\nReact Hooks are functions that 'hook' into different parts of React Components allowing you to do things like updating the view when a variable's value is changed, or running some JS code automatically every time the page is loaded or a variable is changed, and many more cool things! We will primarily focus on three React hooks which are used 95% of the time - **`useState`, `useEffect`, and `useRef`**.\n\n### useState\n\nThere are a lot of times when you want the HTML view to update based on some variable's value changing. We can use the `useState` hook to maintain a variable which automatically re-renders the HTML displayed on the screen every time its value is changed. Here's an example:\n\n```jsx\nfunction ThisWorks() {\n    // myNumber is the variable itself\n    // setMyNumber is a function that lets us update the value\n    // useState(0) initializes the React Hook \n    // with the starting value of 0\n    const [myNumber, setMyNumber] = useState(0);\n    \n    function increment() {\n        // Sets the new value to the old value + 1\n        setMyNumber(myNumber + 1);\n    }\n    \n    return (\n        \u003cdiv\u003e\n            \u003cp\u003e{myNumber}\u003c/p\u003e\n            \u003cbutton onClick={increment}\u003eIncrement!\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cCodeSandbox title=\"intelligent-hoover-31bwmg\" /\u003e\n\nIf you try to run the above code, you will see the view of the web app automatically gets updated to reflect the new value of the variable. \n\nVariables created using `useState` in React are called **State Variables**. State Variables can be updated and automatically update the view of the app. Here's another example of using State Variables with input boxes.\n\n```jsx\nfunction StateWithInput() {\n    // myName is the variable\n    // setMyName is the updater function\n    // Create a state variable with initial value\n    // being an empty string \"\"\n    const [myName, setMyName] = useState(\"\");\n    \n    function handleOnChange(text) {\n        setMyName(text);\n    }\n    \n    return (\n        \u003cdiv\u003e\n            \u003cinput type=\"text\" onChange={(e) =\u003e handleOnChange(e.target.value)} /\u003e\n            \u003cp\u003eHello, {myName}!\u003c/p\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cCodeSandbox title=\"young-microservice-c1e5be\" /\u003e\n\nWe see the text displayed on the HTML changes as the content of the input box changes. Great!\n\n\u003cQuiz questionId=\"27b8acaf-2d9b-4b55-b88f-fd521e3c1aac\" /\u003e\n\nLast thing I want to say about useState is that you can also use it for more than just basic types like strings and numbers. You can also use them to store arrays and objects. However, there is a caveat here. Let's look at an example:\n\n```jsx\nfunction StateArrayDoesNotWork() {\n  const [fruits, setFruits] = useState([]);\n  const [currentFruit, setCurrentFruit] = useState(\"\");\n\n  function updateCurrentFruit(text) {\n    setCurrentFruit(text);\n  }\n\n  function addFruitToArray() {\n    fruits.push(currentFruit);\n  }\n\n  return (\n    \u003cdiv\u003e\n      \u003cinput type=\"text\" onChange={(e) =\u003e updateCurrentFruit(e.target.value)} /\u003e\n      \u003cbutton onClick={addFruitToArray}\u003eAdd Fruit\u003c/button\u003e\n\n      \u003cul\u003e\n        {fruits.map((fruit, index) =\u003e (\n          \u003cli key={index}\u003e{fruit}\u003c/li\u003e\n        ))}\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n\u003cCodeSandbox title=\"kind-jasper-vbs0f9\" /\u003e\n\nIf you try to run this, you will see no fruits get displayed on the screen. Also notice that we are not using the `setFruits` function anywhere, instead just trying to `.push` to the `fruits` array. \n\nWhen we try to update the array directly, React does not register the state change, and that is also considered an invalid state update which can cause the application to behave unexpectedly. We know we need to somehow use `setFruits`, but how? The answer is that we actually need to create a copy of the fruits array, add the fruit to it, and set the state variable to be the new array entirely. Example below:\n\n```jsx\nfunction StateArray() {\n  const [fruits, setFruits] = useState([]);\n  const [currentFruit, setCurrentFruit] = useState(\"\");\n\n  function updateCurrentFruit(text) {\n    setCurrentFruit(text);\n  }\n\n  function addFruitToArray() {\n      // The spread operator `...fruits` adds all elements\n      // from the `fruits` array to the `newFruits` array\n      // and then we add the `currentFruit` to the array as well\n      const newFruits = [...fruits, currentFruit]\n      setFruits(newFruits);\n  }\n\n  return (\n    \u003cdiv\u003e\n      \u003cinput type=\"text\" onChange={(e) =\u003e updateCurrentFruit(e.target.value)} /\u003e\n      \u003cbutton onClick={addFruitToArray}\u003eAdd Fruit\u003c/button\u003e\n\n      \u003cul\u003e\n        {fruits.map((fruit, index) =\u003e (\n          \u003cli key={index}\u003e{fruit}\u003c/li\u003e\n        ))}\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n\u003cCodeSandbox title=\"suspicious-monad-gpes3r\" /\u003e\n\nIf you try to run the above code, you will see it works as expected. Every time you press the button, the current text from the input box is added into the array, which causes the list of fruits displayed on the HTML to be updated. You can keep adding as many fruits as you would like!\n\n\u003e The same is true for Objects as well. If your state variable contains an object, you need to create a copy of the object first, update a value, and then set the state variable to the new object entirely.\n\n## useEffect\nSo we can manage state now, that's great! State changes also affect our rendered HTML, also great!\n\nBut, often times, there is a need to automatically run some code when the page is first loaded - perhaps to fetch data from a server or the blockchain - and also the need to automatically run some code when a certain state variable changes.\n\nThese type of functions are called side effects. React gives us the `useEffect` hook which allows us to write these kinds of effects. `useEffect` takes two arguments - a function and a dependency array. The function is the code that runs when the effect is run, and the dependency array specifies *when* to trigger the side effect. \n\nConsider an example where when the website is first loaded, it wants to load some data from the server. While doing so, it wants to display the user a loading screen, and then once the data has been loaded, remove the loading screen and show the actual content. How do we do this?\n\n```jsx\nfunction LoadDataFromServer() {\n  // Create a state variable to hold the data returned from the server\n  const [data, setData] = useState(\"\");\n  // Create a state variable to maintain loading state\n  const [loading, setLoading] = useState(false);\n\n  async function loadData() {\n    // Set `loading` to `true` until API call returns a response\n    setLoading(true);\n\n    // Imaginary function that performs an API call to load\n    // data from a server\n    const data = await apiCall();\n    setData(data);\n\n    // We have the data, set `loading` to `false`\n    setLoading(false);\n  }\n\n  // loadData is the function that is run\n  // An empty dependency array means this code is run\n  // once when the page loads\n  useEffect(() =\u003e {\n    loadData();\n  }, []);\n\n  // Display `\"Loading...\"` while `loading` is `true`,\n  // otherwise display `data`\n  return \u003cdiv\u003e{loading ? \"Loading...\" : data}\u003c/div\u003e;\n}\n```\n\n\u003cCodeSandbox title=\"practical-cache-ib3c0f\" /\u003e\n\nIf you run the above code from the link, you will see it displays `Loading...` for 5 seconds on the screen, and then displays `ABCDEF`. It's because `apiCall` is a function that just waits for 5 seconds and then returns the string `ABCDEF`. \n\nThe `useEffect` calls `loadData` when the page is first loaded - thanks to the empty dependency array - and the state variables make the HTML render the appropriate content. \n\n---\n\nThis is good for running code when the page first loads, but what about running some piece of code every time a state variable's value changes? For example, when you're searching for a person's name on Facebook, how does Facebook fetch and display recommendations every time you add/remove a character?\n\nYou can also do that with `useEffect`, by providing the state variable in the dependency array. Every time the value of that variable changes, the effect will be run.\n\n```jsx\nfunction DependentEffect() {\n  const names = [\"Alice\", \"Bob\", \"Charlie\", \"David\", \"Emily\"];\n\n  const [recommendations, setRecommendations] = useState([]);\n  const [searchText, setSearchText] = useState(\"\");\n\n  useEffect(() =\u003e {\n    // If user is not searching for anything, don't show any recomendations\n    if (searchText.length === 0) {\n      setRecommendations([]);\n    } \n    // Else, find recommendations\n    else if (searchText.length \u003e 0) {\n      const newRecs = names.filter((name) =\u003e\n        name.toLowerCase().includes(searchText.toLowerCase())\n      );\n      setRecommendations(newRecs);\n    }\n  }, [searchText]);\n\n  return (\n    \u003cdiv\u003e\n      \u003cinput type=\"text\" onChange={(e) =\u003e setSearchText(e.target.value)} /\u003e\n      \u003ch2\u003eRecommendations:\u003c/h2\u003e\n      \u003cul\u003e\n        {recommendations.map((rec, index) =\u003e (\n          \u003cli key={index}\u003e{rec}\u003c/li\u003e\n        ))}\n      \u003c/ul\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n\u003cCodeSandbox title=\"cold-darkness-eub0eh\" /\u003e\n\n\u003cQuiz questionId=\"e27e7555-0f31-429f-ac77-207373149378\" /\u003e\n\nIf you run the above code, and try typing some letters, you will see the recommendations list automatically gets updated as you add/remove new characters in the search box. This is because when you update the input box, the value of `searchText` is updated through the `onChange` handler, which triggers the `useEffect`, which updates the `recommendations` list, which updates the HTML view.\n\n\u003cQuiz questionId=\"53346a89-ee63-4318-b9c4-ea016e0b5def\" /\u003e\n\nYou can also similarly create side effects which are dependent on multiple state variables, not just one. If any of the dependent variables change, the side effect is run. You do this by just adding more state variables to the dependency array.\n\n```jsx\nuseEffect(() =\u003e {\n    // Some code\n}, [stateVar1, stateVar2, stateVar3, andSoOn])\n```\n\n\u003cQuiz questionId=\"3f615f81-ab26-486b-9665-e9615f4a1b8d\" /\u003e\n\n### useRef\n`useRef` is another React hook that is somewhat commonly used. It is quite similar to `useState` on the surface, but has some subtle differences that are actually quite important which make this React Hook important to learn. \n\n`useRef` variables are created as follows:\n\n```jsx\nfunction Component() {\n    const myValue = useRef();\n    \n    function updateMyValue(newValue) {\n        myValue.current = newValue;\n    }\n    \n    function printMyValue() {\n        console.log(myValue.current);\n    }\n}\n```\n\n#### #1 - No Re-Rendering\nSimilar to `useState`, the `useRef` hook also allows us to store a variable in a component that can be updated over time. But, unlike state variables, updating the value of a ref variable does not cause the HTML view to re render. \n\nTherefore, if you had a `useRef` variable and you were displaying it's value in your HTML view, updating the variable will **not** update the HTML view. \n\n```jsx\nfunction CounterWithRef() {\n    const myNumber = useRef();\n    \n    function increment() {\n        if (myNumber.current !== undefined) {\n            myNumber.current += 1;\n        } else {\n            myNumber.current = 1;\n        }\n        console.log(myNumber.current);\n    }\n    \n    return (\n        \u003cdiv\u003e\n            \u003cp\u003e{myNumber}\u003c/p\u003e\n            \u003cbutton onClick={increment}\u003eIncrement!\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cCodeSandbox title=\"small-paper-9ecbfp\" /\u003e\n\nIf you run the above code, you will notice that every time you click the button, the value is incremented and printed in the browser console, but the HTML view doesn't actually update. In fact, the HTML view doesn't display anything, because the initial value of `myNumber.current` is `undefined` and since the HTML doesn't update, it stays `undefined` as far as the HTML is concerned even though the value is actually being updated.\n\n#### #2 - Synchronous Updates\n\n![](https://i.imgur.com/QZk8FcK.jpg)\n\n![](https://i.imgur.com/ujZNqIA.jpg)\n\nSomething we didn't mention before about `useState` is that when we update a state variable using the `setXYZ` functions, it actually doesn't get updated instantly.\n\nSetting a new value for state variables happens asynchronously in React, which means if you try to use the state variable's value immediately after setting it to a new value, you might not actually see the new value being reflected as it happens asynchronously.\n\nLet's take a look at the Counter example again when using `useState`. \n\n```jsx\nfunction AsyncStateVariables() {\n  const [number, setNumber] = useState(0);\n\n  function increment() {\n    setNumber(number + 1);\n    console.log(number);\n  }\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003e{number}\u003c/p\u003e\n      \u003cbutton onClick={increment}\u003eIncrement\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n\u003cCodeSandbox title=\"reverent-lichterman-k4n448\" /\u003e\n\nWhen you run this, notice what happens on the view and what happens in the console. When you first click the button, the state variable should be updated to `1` - and that's what happens on the view, the web page displays `1`. But if you look at the browser console, the value `0` is printed instead of `1`. This pattern continues as you keep clicking the button. \n\nThis is because the `setNumber` call runs asynchronously, and by the time we reach the `console.log(number)` line, the value hasn't been updated yet, so it prints the old value of `number`. When it does in fact gets updated, the HTML is re-rendered to display the new value. \n\n---\n\n`useRef` on the other hand, allows for synchronous updates. When you update the value of a reference variable using `myVar.current = newValue` it is instantly updated, and there is no delay. This can come in handy sometimes. \n\n#### #3 - Referencing DOM Elements\nAnother cool thing that `useRef` lets us do is that it allows us to refer directly to DOM elements. This is something that is not possible with `useState`. \n\nFor example, you can reference an `input` element directly using `useRef`\n\n```jsx\nfunction InputFocus() {\n  const inputRef = useRef();\n\n  useEffect(() =\u003e {\n    inputRef.current.focus();\n  }, []);\n\n  return \u003cinput ref={inputRef} type=\"text\" /\u003e;\n}\n\n```\n\n\u003cCodeSandbox title=\"input-focus-zntci\" /\u003e\n\nWhen you run this above example, you will notice that as soon as the page loads, the `input` element is already in focus i.e. you can start typing without clicking on it first. This is because we hold a reference to the `input` element, and have a `useEffect` that runs on page load due to having an empty dependency array, that focuses on the `input` element.\n\n\u003cQuiz questionId=\"a5533750-da4a-42a4-81d0-2afb9009a529\" /\u003e\n\n## React File Structure\nGreat, we have covered the main concepts you should know if you're just getting started with React. But so far, we have only dealt with isolated component examples. How does an actual React project look like?\n\nReact applications are typically created using a tool like `create-react-app` (CRA). CRA is a command-line tool that helps you setup new React projects and install all the required dependencies without you needing to manually create all the boilerplate.\n\nWhen you use CRA, you will end up with a file structure that looks like this.\n\n![](https://i.imgur.com/4ANKkGn.png)\n\nThe `package.json` file should be recognizable. CRA works through a Node.js environment, and `package.json` is where all the dependencies and project metadata is created - as with any other Node.js project.\n\nThe `src/` folder houses the components and CSS styling, basically any React-specific code. The main component here is `App.js`, which is the autogenerated component that is created when you first set up a React application. `index.js` is the main entrypoint of the React application, but typically you would not need to modify it very much (or at all). It just contains some boilerplate React code that takes your components and converts it into actual HTML and JS that can be run in a browser.\n\nThe `public/` folder then contains only one file by default - `index.html`. You would usually never touch this yourself. This is a super simple barebones HTML file. When a React app is run, React does some magic under the hood that takes all your components and Javascript code, converts it to actual HTML and JS that can run in the browser, and replaces the contents of `index.html` with all of that. Then, the updated `index.html` is what is displayed to the user.\n\nIf you wanted to add images, fonts, music, etc. to your website, they would also go into the `public/` folder. The `public/` folder basically contains everything you want to be directly accessible on your website.\n\nFor example, if you added an image called `avatar.png` into your `public/` folder, you can then display that image within a React component as such:\n\n`\u003cimg src=\"/avatar.png\" /\u003e`\n\nWhile this may seem weird because your component lives inside the `src/` folder and not the `public/` folder - the reason it works is because the image lives in the same folder as `index.html` - and `index.html` is where your React code actually ends up. So when referencing an image using the relative path of `/avatar.png`, it knows that `avatar.png` must be inside the `public` folder.\n\n## Backend Time\n![](https://i.imgur.com/eU81Qd0.png)\n\n\nSo far we have been discussing React, and all it's frontend capabilities. But what about backends? \n\nReact is not a backend framework, so if you wanted to create your own API backend, you would have to set up a separate project using something like Node.js and Express. This is however cumbersome, as if the backend and frontend are for the same project, you likely have a lot of code that can be reused and shared across the two. Additionally, maintaining two projects is always harder than maintaining just one.\n\nEnter, Next.js\n\nNext is a meta-framework for React. What does this mean? Well, React itself is a framework for building web apps. Next, on top, is a framework for React that also introduces a few additional features that React did not have.\n\nIf you know React, Next is 90% the exact same thing and you can get started using it very quick, but I want to talk about these extra features that Next brings.\n\nFirst of all, as the title and intro may have hinted to you, Next allows you to write both Frontend and Backend code in a single project. You build your frontend using React, and write your backend API endpoints in a similar syntax as using Express - but all in the same project.\n\nSecondly, Next makes creating multi-page web apps very easy. React was originally designed to help create Single-Page Applications (SPAs), and components are great for that! But what if your website has multiple pages? For example `https://learnweb3.io/` and `https://learnweb3.io/about` and `https://learnweb3.io/tracks` etc.\n\nFor this, libraries such as `React Router` were introduced, which made it possible, but also were a bit cumbersome. 'Next' simplified this a lot by allowing for automatic page routing based on filename. \n\nLastly, Next also features Server Side Rendering (SSR) and Static Site Generation (SSG). These are not features we will use within our tracks, so I will not spend too much time here, but feel free to go through the Recommended Readings later on if you'd like to learn more about them.\n\n### Routing in Next\nWe will discuss Routing before we discuss creating a backend server, because this will help you understand how that works as well.\n\nSimilar to `create-react-app`, Next has a tool called `create-next-app` that can automatically help you setup new Next.js projects with ease.\n\nWhen you create a new Next.js project, you will end up with a file structure that looks like this:\n\n![](https://i.imgur.com/KDx0RzY.png)\n\nThis is lot of files! But don't worry, a lot of it is similar to what we have already discussed for React.\n\nThe `public/` folder works exactly the same way, with the exception of not containing an `index.html` file. However, if you wanted to add images, icons, fonts, music, etc. you would place them all in the `public/` folder.\n\nThe `styles/` folder is a good addition, providing a dedicated spot for all your CSS files.\n\nThe `pages/` is what's great. `_app.js` is an autogenerated file that usually you will not be touching yourself, and sets up some boilerplate code that allows Next to render the proper components.\n\n`pages/index.js` is the homepage of your website. Basically, every file within the `pages` folder is a route of your website. Following Javascript/HTML-style naming conventions, this means that `index` files are the 'main' files. Therefore, `pages/index.js` is the view that will load up when you first open up your website.\n\nIf you add more files under the `pages` folder, for example a file named `about.js` - it will be available at `YOUR_DOMAIN/about` (Fun Fact: LearnWeb3's website is created using Next, and that is exactly how our `https://learnweb3.io/about` page works).\n\nThis is great because you don't have to deal with things like React Router, and building multi-page websites is as simple as just creating a new file under the `pages/` folder and Next will automatically generate a route based on the filename for you.\n\nYou can also do multilevel routing by creating subfolders under the `pages/` folder. For example, something like `pages/tracks/freshman.js` will have the route `YOUR_DOMAIN/tracks/freshman`.\n\n\u003cQuiz questionId=\"f6735f24-7539-4998-bb46-3e5c00b14afd\" /\u003e\n\n### Writing APIs in Next\nThere is one special folder under `pages/` however which was also autogenerated. The `pages/api` folder. Unlike regular pages, which render HTML views, anything under the `pages/api` folder acts as an API endpoint.\n\nLet's look at the autogenerated `pages/api/hello.js` file:\n\n```js\nexport default function handler(req, res) {\n  res.status(200).json({ name: 'John Doe' })\n}\n```\n\nThis is a very Express-like function. If you were to go to `YOUR_DOMAIN/api/hello` - instead of rendering an HTML view, this will return a JSON object `{name: 'John Doe'}` - which is a super simple API endpoint.\n\nSimilar to regular HTML views, you can create API endpoints under `pages/api` just by creating new files, and the endpoint routes are based on the filename.\n\n\u003cQuiz questionId=\"ff3c1f4e-f2c4-4d8f-9c51-bec1cc201c01\" /\u003e\n\n## Conclusion\nI hope this article was helpful to you and can act as a crash course. I deliberately focused more on React than Next here, as getting used to the Frontend part is going to be more relevant for us than the Backend part. Also, backend code is basically regular Javascript, whereas Frontend is JSX which I wanted to get you more comfortable with.\n\nI've listed some additional readings and videos that I would recommend to get an even better understanding of these concepts. As always, if you have any questions, message on the `#web2-support` channel on [Discord](https://discord.gg/learnweb3) and we'd be happy to help.\n\n## Readings/Videos\n\n- [Learn React in 30 Minutes](https://www.youtube.com/watch?v=hQAHSlTtcmY)\n- [Next.js in 100 Seconds // Plus full tutorial](https://www.youtube.com/watch?v=Sklc_fQBmcs)\n- [Scrimba's Full React Course](https://scrimba.com/learn/learnreact)\n- [Next.js Crash Course](https://www.youtube.com/watch?v=mTz0GXj8NN0)\n\n## DYOR Questions\n\u003cQuiz questionId=\"0998b476-55c7-4386-9313-e917b15e695a\" /\u003e\n\n\u003cSubmitQuiz /\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnweb3dao%2Fjust-enough-react-and-nextjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flearnweb3dao%2Fjust-enough-react-and-nextjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flearnweb3dao%2Fjust-enough-react-and-nextjs/lists"}