# React Notes ###### tags: `React` `JavaScript` `GUI` `App` `Web Technology` ![](https://hackmd.io/_uploads/B1jELct-p.png) Learn React as a beginner with JavaScript development experience. ref: - [從 JavaScript 到 React - Next.js](https://hackmd.io/@shibarashinu/HyLUtS173) - [Learn React - React.dev](https://react.dev/learn/describing-the-ui) - [React Hooks - w3schools](https://www.w3schools.com/react/react_hooks.asp) - [30 Days Of React - github](https://github.com/Asabeneh/30-Days-Of-React) impl tutorial: - [Build and Deploy an Amazing 3D Web Developer Portfolio in React JS | Beginner Three.js Tutorial - JavaScript Mastery](https://www.youtube.com/watch?v=0fYi8SGA20k) - [Build and Deploy a React Native App | 2023 React Native Course Tutorial for Beginners - JavaScript Mastery](https://www.youtube.com/watch?v=mJ3bGvy0WAY) - [Build and Deploy a React Admin Dashboard App - JavaScript Mastery](https://www.youtube.com/watch?v=jx5hdo50a2M) ### Using React Scenario The React framework is a library that manipulates UI components, creating a logical, MVC encapsulation module. And it also take advantage of optimizing the DOM tree lifetime updates and the rendering processes. ### Basic usage 1. use React library & JSX compiler (Babel) ```jsx= // React library <script src="/js/react-core.js"></script> <script src="/js/react-dom.js"></script> // Babel (for compiling following JSX) <script src="/js/babel.js"></script> <script type="text/jsx"> const app = document.getElementById("app"); ReactDOM.render(<h1>Hello</h1>, app); </script> ``` 2. JSX syntax ```jsx= <script type="text/jsx"> function MyComponent() { return ( <div class="component"> <MyContainer objItem="i" objItem2="i2" /> <MyContainer objItem="ii" arr={ [ "li0", "li1" ] } /> </div> ); } function MyContainer({ objItem, objItem2, arr }) { return ( <div class={ `${objItem}-my-container` }> // class="i-my-container" { objItem2 || "default" } // "i2": { ... } JSX syntax escape characters to javascript </div> <div> {arr.map((item) => ( <li key={item.id}>{ item }</li> // key: React "id" to identify different components ))} </div> ); } const app = document.getElementById("app"); ReactDOM.render(<div><MyComponent /></div>, app); </script> ``` 3. DOM event listener ```jsx= function Banner() { function homeClick() { window.location = "/"; } return ( <div> <a onClick={homeClick}>Home</a> </div> ); } ``` 4. useState (for every Component) ```jsx= import { useState } from 'react'; function HomePage() { const [ storeValue, setValue ] = React.useState("init value"); const [ value2, setValue2 ] = React.useState("init value2"); return ( <a onClick={ ()=>setValue("clicked") }>{ storeValue }</a> ); } ``` 5. useRef (1. no new rendering process triggered compared to useState / 2. ref hook to get dom element) ```jsx= import { useRef } from 'react'; function SendButton() { const ref = useRef("init"); return ( <button onClick={ ()=>{ ref.current = ref.current && "send"; } } /> ); } ``` ```jsx= import { useRef } from 'react'; function App() { const componentRef = useRef("init"); useEffect(()=> { if(!!componentRef.currect) console.log(componentRef); }) return ( <Component ref={componentRef} /> ); } ``` 6. useReducer (states transition: initial => case dispatch => new state) [A cure for React useState hell - Steve (Builder.io)](https://www.youtube.com/watch?v=sGdW4Amolq4&ab_channel=Steve%28Builder.io%29) ```jsx= const dispatcher = { add: (state) => { count: state.count + 1 }, // return blend new obj as new state instead of modified state sub: (state) => { count: state.count - 1 } } function reducer(state, action) { const dispatchFunc = dispatcher[action.type]; return dispatchFunc ? dispatchFunc(state) : state; } const Buttons = () => { const [state, dispatch] = useReducer(reducer, { count: 0 }); const addClick = () => { dispatch({ type: "add" }) }; const subClick = () => { dispatch({ type: "sub" }) }; return ( <div> <button onClick={ addClick } /> <button onClick={ subClick } /> </div>); }; ``` 7. useContext (for interior-cross var get / set within Component block) ```jsx= // Context-definition-lib.js import { createContext } from 'react'; export const MyLayerContext = createContext({ level: 0, name: "root", state, setState }); ``` ```jsx= // Component.js import { useState, useContext } from 'react' import { MyLayerContext } from './Context-definition-lib.js' export default function Section({ children }) { const [state, setState] = useState("initial"); const parentLayerContext = useContext(MyLayerContext); return ( <section> <div>{ name + '-' + layer }</div> <MyLayerContext.Provider value={{ layer: parentLayerContext.layer + 1, name: "section", state, setState // so children can get / set parent provider's state }} > { children } </MyLayerContext.Provider> </section> ); } ``` 8. useEffect (== Component drawcall) :::warning **Virtual DOM Management** If a virtual DOM's element is unmounted, React bottom-up cleans up the corresponding subtree, that is: 1. remove the element from the actual DOM tree. 2. remove internal references, corresponding resources & invoke their cleanup callbacks, so to prevent memory leaks. ::: ```jsx= import { useState, useEffect } from 'react' function Timer() { const [state, setState] = useState(0); useEffect(() => { setTimeout(() => { setState((origin) => origin + 1); }, 1000); const cleanupFunc = () => { db.disconnect(); }; return cleanupFunc; }, [state, state2]); // <- render if any dependency value changes return <div>state: {state}</div>; } ``` (8-2. useLayoutEffect (sync drawcall)) 9. useCallback (call this Component to render if the observed variables have changed) ```jsx= const Arr = ({ arr, insert }) => { return ( <> <h2>My Array</h2> { arr.map((item, ind) => (<p key={index}>{todo}</p>)) } <button onClick={ insert }>Add Item</button> </> ); }; const App = () => { const [arr, setArr] = useState([]); const insert = useCallback(() => { setArr((arr) => [...arr, "new item"]); }, [arr]); return <Arr arr={arr} insert={insert} />; }; ``` 10. useMemo (same as useCallback but use it as a React component) > [useMemo vs. useEffect + useState - StackOverflow](https://stackoverflow.com/questions/56028913/usememo-vs-useeffect-usestate) > The `useEffect` and `setState` will cause extra renders on every change: the first render will "lag behind" with stale data and then it'll immediately queue up an additional render with the new data. > ```jsx= > function expensiveCalculation(x) { return x + 1; }; > ``` > Lets suppose x is initially 0: > - The `useMemo` version immediately renders 1. > - The `useEffect` version renders null, then after the component renders the effect runs, changes the state, and queues up a new render with 1. > > Then if we change x to 2: > - The `useMemo` runs and 3 is rendered. > - The `useEffect` version runs, and renders 1 again, then the effect triggers and the component reruns with the correct value of 3. ```jsx= const App = () => { const [count, setCount] = useState(0); const result = useMemo(() => expensiveCalculation(count), [count]); const increment = () => { setCount((count) => count + 1); }; return ( <div> Count: {count} <button onClick={increment}>+</button> <h2>Expensive Calculation</h2> {result} </div> ); }; const expensiveCalculation = (num) => { for (let i = 0; i < 1000000000; i++) { num++; } return num; }; ``` 11. useQuery (auto fetch when var changed) ```jsx= const result = useQuery("/api/books", { var }); ``` 100. my custom use hook ```jsx= const myUseFetch = (url) => { const [data, setData] = useState(null); // ! concatenate the React useState hook useEffect(() => { fetch(url) .then(res => res.json()) .then(data => setData(data)); }, [url]); return [data]; }; export default myUseFetch; ```