# React Training 101 ## Starting Off If you aren't familiar with Javascript or want to make sure to fill in the gaps, read through this javascript primer from MDN: [Javascript Basics](https://developer.mozilla.org/en--US/docs/Web/JavaScript/A_re-introduction_to_JavaScript) This content is inspired by the React [docs](https://reactjs.org/docs/getting-started.html). ## What is React? At the highest level, React is a Javascript library that is the "View" in the MVC (model/view/controller) pattern. React components allow you to represent your application data in a tree of reactive components. "Reactive" meaning they re-render when data changes. Your entire app could be a giant tree of components or you could have mini-component trees in various parts of your existing application. ## Why React? Before React, Angular, Vue and all the other front-end libraries, lots of developers used JQuery, MooTools and others. These frameworks were very powerful at the time, but have since been replaced and are no longer recommended. There are many reasons for this shift, but let's look at a couple primary benefits of upgrading to something like React. ### Marketability The demand for React is strong. One day it may not be, but today it is one of the most popular front-end libraries and is only gaining more solidarity as frameworks are built off of React like Next.JS, Remix and others. ### Component-based architectures Before React it was not uncommon to have a convoluted, messy UI. Simply because there was not a strong set of best practices adopted by the community. By using a component-based architecture you can encapulate common code together and it becomes much easier to decipher what is going on. Debugging is easier. Making updates is easier. ### DOM Mutations are Expensive It is expensive and slow to manipulate the DOM. This is how you made UI updates in tools like JQuery. React solved this by introducing a virtual DOM and a render cycle. By abstracting DOM changes away from the physical DOM to a virtual DOM, React allows you to continue to make changes to a UI and only manipulate the DOM once. This is described as the "render" phase and the "commit" phase. You'll learn more about that below. #### Fiber The goal of react is to reconcile changes and flush them to the dom as quickly as possible. To do this, React currenly uses a reconciliation algorithm called "Fiber". A good, in-depth explaination can be found [here](https://indepth.dev/posts/1008/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react) ##### A Fiber A fiber is both a description of work but also a node representing a persistent thing. **Example:** element: <div> </div> fiberNode: `{type: 'div', stateNode: HTMLDIVElement, tag: [WhatKindOfFiber...not html tag, example: FunctionComponent or HostComponent(div, p, spans)]}` **There are typically 2 fiber trees.** 1) A "work in progress" tree 2) the current fiber tree Note: There is a root fiber that is created when you call render and provide a root element. This root fiber node points at the current fiber tree. Another Note: Once the "work in progress" tree completes, the root fiber node just points to the WIP tree and then the current tree becomes the new WIP tree. This allows for things like if you were to start updating a feed, but someone clicks "Like", the WIP tree can be thrown away and ran with the "Like" changes. This ability to throw away the current work and run some new changes is why the new fiber tree concept was created. Prior to React 16, the tree was mutated top down, so this was not possible and now with this approach React can do concurrent mode. **There are 3 phases:** 1) Begin (starting down the tree) 2) Complete (end of tree) 3) Commit (change of pointer to new fiber tree for root) Events trigger in different phases: **Render** - constructors - componentWillMount - componentWillReceiveProps - shouldComponentUpdate - componentWillMount - render Could call 2x, 3x, any number of times, or not at all! **Commit** - componentDidMount - componentDidUpdate - componentWillUnmount Only calls them once! Safe for side effects. ## Writing Components Each component in your apps tree is written using a special extension to the javascript language called JSX. JSX stands for Javascript and XML and once you get the hang of it, it is really nice! The syntax can turn off some folks initially, but in time you get used to it. Dive more into JSX in the docs [here](https://reactjs.org/docs/introducing-jsx.html). What does it look like? ```javascript <SomeJSXElement>Hello World</SomeJSXElement> ``` In order to make this work, Facebook took advantage of a tool called [babel](https://babeljs.io/) and created a plugin that transforms JSX into regular old javascript that a browser can understand. So, you write this: ```javascript <SomeJSXElement>Hello World</SomeJSXElement> ``` And babel transforms it into this: ```javascript React.createElement(SomeJSXElement, null, "Hello World"); ``` There is nothing stopping you from writing all your React using `React.createElement(...)` however it will be painful and is generally not recommended. ## Props vs State Components don't do much without having some sort of properties set or some local state. Here are some general rules when it comes to props vs state: - Props are passed down the component tree. - State is localized to the component it is used in, but can also be passed down to child components as a prop. - Global state is achieved through `Context`, which we will discuss later. ### Example **Props** In the example below, "name" is considered a prop of the "MyComponent" component. It is passed to the component like so: `<MyComponent name="Sarah" />` If you want to update a prop, you'd typically also pass a function to your component that would provide the new value for the prop. For example, `<MyComponent name="Jim" updateName={updateName} />` **State** "favoriteColor" is considered state and is updated by calling the "setFavoriteColor" function. - You might update it after clicking a button or typing into a textbox. ```javascript const MyComponent = ({ name }) => { // This is using array destructing // The default value for "favoriteColor" will be "Green" const [favoriteColor, setFavoriteColor] = useState("Green"); return ( <div> Hi {name}! Your favorite color is {favoriteColor}. </div> ) } MyComponent.defaultProps = { name: "Foo" } MyComponent.propTypes = { name: string } ``` ## Designing Components When beginning to design a component or an entire page in React it is helpful to approach things using this technique: - Whiteboard or write up static HTML first - Decide where it makes sense to extract your components given the UI - Consider what props or state each component will need: - Pay attention to… - Shared props - What props are needed across multiple components? - Does it make sense to keep track of these props in the parent component or is something that should be in context? Usually parent component is the best place to start until you need it else where. - Local state - What can be localized to the component? - Create your components - Make sure to add your propTypes and defaultProps Read more about this strategy [here](https://reactjs.org/docs/thinking-in-react.html) ## Function vs Class Components There are generally two approaches to writing components; function components or class components. Both are valid ways to express React components. Class components are a great way to learn, however there is a movement towards using Function components and hooks, so that should be the focus. There are exceptions, such as `ErrorBoundary` components that must be class based, but otherwise, it is recommended to use function components. ### Examples #### Function Components There are a couple ways to express function components. All of these are the same, just different ways of doing things. Using a fat-arrow function: ``` const MyComponent = ({name}) => { return ( <div>Hello, {name}</div> ) } ``` This can actually be even cleaner, which is sometimes why the fat-arrow function is preferred: ``` const MyComponent = ({name}) => <div>Hello, {name}</div> ``` Using a named function: ``` function MyComponent({name}) { return ( <div>Hello, {name}</div> ) } ``` #### Class Components ``` class MyComponent extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } } ``` ## Lifting State Up No matter how much design you do up front, one will inevitably run into a scenario where more than one component needs access to some local state. In this case, you will want to lift your state up the component hierarchy so you can pass the state back down as "props". The React docs explain this quite well [here](https://reactjs.org/docs/lifting-state-up.html) ## Inverse Data Flow Sometimes you have a parent and a child component that needs to update state. You simply pass a handler down from the parent and let the child call the handler with the new value. See Example: ``` const Parent = () => { const [email, setEmail] = useState(''); const handleChange = updatedEmail => setEmail(updatedEmail) return ( <> Email: {email} <Child onChange={handleChange} value={email} /> </> ) } const Child = ({ onChange, value }) => { return ( <div> <label>Email</label> <input type="text" value={input} onChange={e => onChange(e.target.value)} /> </div> ) } ``` ## Global State There are times when you will need to access something deep down in the component tree and also at the top. Rather than passing those props down through the component tree (called prop drilling), you can use "context". To use context... - You must first create it. - Then you provide the context to your components by wrapping them in a "Provider" - You then gain access to context by using the `useContext` hook Read more [here](https://reactjs.org/docs/context.html) ### Example ``` // Create context const MyContext = React.createContext(); // Provide it to your app using a Provider const App = () => { const [theme, updateTheme] = useState(); return ( <MyContext.Provider value={{ theme, updateTheme }}> <Container> <Header /> <Content /> <Footer /> </Container> </MyContext.Provider> ) } // Then, let's say down in your <Content /> component you want // to access the theme: const Content = () => { const { theme } = useContext(MyContext); return ( <div> You are using the {theme} theme! </div> ) } ``` ## Hooks A fairly recent update to React was the introduction of hooks. These are simply special functions that start with "use", abide by some rules and allow you to do things in function components that were previously achieved via higher order components or class components. Let's take a look at a few common hooks. If you are eager to dive in, check out the docs [here](https://reactjs.org/docs/hooks-intro.html) ### useState Any time you want to keep track of something that you will be changing over time and want to tell React to re-render when it changes, you'll use the `useState` hook. Read more [here](https://reactjs.org/docs/hooks-state.html) **Example** ``` const [name, setName] = useState("Jim") ``` ### useEffect Any time there is some sort of side effect, you'll want to use a `useEffect` hook. Read more [here](https://reactjs.org/docs/hooks-effect.html) **Example** ``` // This will run every render useEffect(() => { console.log("I ran!") }) // This will run every time the "loading" prop changes useEffect(() => { console.log(loading) }, [loading]) // This will run every time the "loading" prop changes // and will also run a function returned from the useEffect // hook when this component is removed from the DOM useEffect(() => { console.log(loading) return () => { console.log("This is where you can run clean up code!") } }, [loading]) ``` ### useLayoutEffect Works the same as `useEffect`, but you'll want to use this if you are doing any sort of measuring of style-related things with the DOM. Essentially, if you find yourself accessing HTML elements properties like height or width, you will want to use the `useLayoutEffect` hook. Read more [here](https://reactjs.org/docs/hooks-reference.html#uselayouteffect) ### useRef Allows you to keep track of something for the lifetime of your component. This is often used to access the native DOM element associated to some JSX element. Read more [here](https://reactjs.org/docs/hooks-reference.html#useref) **Example** ``` const MyComponent = () => { const inputRef = useRef(null); const doIt = () => { // Output the background color for the div console.log(inputRef.current.style.backgroundColor) } return (<> <div ref={inputRef} style={{backgroundColor: "#123"}}>Hello World</div> <button onClick={doIt}>Click Me</button> </>) } ``` ## Rules of Hooks There only a couple rules one must abide by in order for Hooks to work in the React world. 1) Hooks must be first 2) Hooks can only be using in function components or other hooks Read more [here](https://reactjs.org/docs/hooks-rules.html) ## Render and Portals There are a couple ways to render React components. The most common way in the web-world is to call `react-dom`'s `render` method. The other way is by using a `portal`, which allows you to basically inject a React component anywhere in your site. Sometimes you aren't working with a 100% React application. For example, if you are working on a WordPress site where you want to use React for a dropdown menu at the top of the page and a specialized store locator tool. This is where you'd want to lean on React's `portal`. Read more [here](https://reactjs.org/docs/portals.html#gatsby-focus-wrapper) ## Mapping Data and Keys Often times you will be displaying a list of things. If you find yourself using `map`, make sure to provide each item with a `key`. Read more [here](https://reactjs.org/docs/lists-and-keys.html#keys) **Example** ``` data.map(item => <li key={item.id}>{item.label}</li>) ``` ## Odd Html Attributes One oddity of React is that they had to slightly adjust some HTML attributes in order to have it jive with the ones already established for native HTML elements. **Some examples:** - Rather than`<div class=...`, you'd use `<div className=...` - Rather than`<button onclick=...`, you'd use `<button onClick=...` - Rather than`<label for=...`, you'd use `<label htmlFor=...` Be on the look out for these! There are only so many and if you do happen to make a mistake, React is pretty good about yelling at you in the console. So, be sure to pay attention to those console warnings! ## More Advanced Topics - [Intro to React Tutorial](https://reactjs.org/tutorial/tutorial.html) - This React tutorial will help solidify what we covered above. - [Explore more React](https://reactjs.org/docs/hello-world.html) - There are many other aspects of React not mentioned above, so if you would like to explore other areas, feel free to peruse. - [Create React App](https://create-react-app.dev/docs/getting-started) - This is the defacto standard for creating new React apps. This is where you want to start if you want to quickly get going with your very own React app. - [Redux](https://react-redux.js.org/introduction/basic-tutorial) - This is a common library used to keep track of your application state in "stores". It is an essential ingredient in many React apps and although you may not need to use redux all the time, it is important to understand the concepts of reducers, stores and actions. ### Frameworks - [NextJS](https://nextjs.org/) - React is considered a library, where as Next.js is considered a framework. There are many rules and conventions that Next.js has adopted and although it is overwhelming to try and just learn Next.js, it is helpful to at least be aware of it and know when you might want to use it. - [GatsbyJS](https://www.gatsbyjs.com/) - Another React framework for building static web sites. This is great for blogs and many other sites. The learning curve here is steep, similar to Next.JS, so take it slow and this is another to be aware of in the case where it makes sense for you to use. - [Remix](https://remix.run/) - Yet another React framework. This framework does cost money to use, but if you are looking to get going fast with a robust framework, this may be it.