React
reduce in JS vs useReducer
1) reduce and useReducer take function and initial state 2) reducer function defined for an accumulator and an item value - this gets returned to one value - in useReducer, the newState is calculated from the currentState, and an action) - the action parameter determines state transition from current state to new state 3)Return values: - reduce returns a single value - useReducer returns a pair of values: [newState, dispatch] Reducer ex: const currentArray= [1, 2, 3, 4]; const reducer = (accumulator, currentValue) => accumulator + currentValue; currentArray.reduce(reducer) // 10 currentArray.reduce(reducer, 5) //15 (5 is initial value)
componentDidUpdate()
called after prop or state changes -can call setState but will need to check against prevProps
How to debug a project
console.log inspector debugger statements React Developer Tool useDebugValue
Benefits of typescript
developer productivity, predictability, allows code and unit tests to be more directly focused on business logic
Session Cookies vs JWT
https://hackernoon.com/using-session-cookies-vs-jwt-for-authentication-sd2v3vci
Can you modify props?
no - props are readonly - because functions are supposed to be pure components - if you want to modify things, you can modify state
react-error-boundary for functional components
popular package that provides reusable error boundary component
Why can't you update state directly without setState?
setState triggers re-rendering the component - we do want to re-render component
Context vs Redux
- context is good for low frequency updates (like locale/theme) - and its good for static values that then propagate updates through subscriptions - Context suffers from having to choose multiple nested context providers vs one giant context provider. Context is also not performant for high-frequency state changes - for high frequency changes - use redux
React vs jQuery
- jQuery works with Real DOM - React works with Virtual DOM - if you were to use both React and jQuery in one app, you may have conflicts (controlled components are solution to this problem)
Shallow Comparison
1) Primitive Types (numbers, strings, booleans) - return true if a and b have same value and are of the same type 1) Complex Types (objects, array) - return true if a and b reference the exact same object
Pure Functions and how they relate to Pure Components
Just like pure functions are optimized/cached and save time when called with the same input, Pure Components don't re-render for the same input Pure Component best practices: a) good idea to ensure all child components of a PureComponent are also "pure" to avoid unexpected behavior b) Never mutate the state, always return a new object that reflects the new state
Why you might not use Redux?
redux gives global state - good if you want to handle data in throughout app Reasons not to use redux - simple react app with no need for a global state
Single Page App vs Multi Page app
Single Page App Pros - smooth user experience - app more interactive/fast navigation - better performance => with proper lazy loading you're only loading a small portion (however the javascript - cross platform compatibility => single code base used to build apps that run on any browser or device Single Page App Cons - slow initial loading if JS is considerably bigger - compromised SEO => search engine has to deal with JS rather than html - degraded website traffic metrics Multi-Page App Pros - Better SEO => since each page has its unique URL/metadata (search engines can crawl/index individual pages more effectively - improving discoverability / ranking in search results) - potentially more scalable - can add as many pages as you want without affecting load perf (MPA good choice for large projects) SPA => small to medium projects with focus on speed,efficiency, and user experience MPA => larger projects with focus on scalability, SEO, and ease of maintenance
setState in render
causes infinite loop
React Virtual DOM
- an internal representations of rendered UI - includes all React elements you return from components. Virtual DOM is a JSON object that is extremely fast compared to browser DOM. It is created entirely from scratch on every setState anywhere in app - state change ==> update entire virtual DOM tree (fast) ==> diff previous and current version of virtual DOM ==> send batched updates to real DOM for repainting -Virtual DOM update is more efficient by batching and delaying DOM changes until the end to prevent reflow/redraws. (page redraws are costly - have to recalculate the css, do layout, repaint the web page). A list of the minimum possible differences between Virtual DOM and real DOM are created, and only calculate repaint/paint one time. - real DOM updates are batches all as DOM writes (since DOM reads cause repaint) -reconciiliation is O(n) https://reactjs.org/docs/reconciliation.html - can use shouldComponentUpdate lifecycle method to prevent rerendering
Arrow functions
- auto bind 'this' to the surrounding context (lexical scoping) -this *prevents the need for binding event handlers* https://reactjs.org/docs/handling-events.html - in picture example, Headline component uses object destructuring to get props.value https://www.robinwieruch.de/react-function-component
Constructor optional?
- babel supports class fields - so you can initialize state without the need for a constructor class MyComponent extends Component { state = { counter: 0, }; } - constructor can bind methods if needed - constructor can initialize ref -must call super(props) in constructor
React Context - Multiple Provider vs One Large Provider
- can have multiple different context providers - or one giant context with multiple purposes
PureComponent Summary
- implements shouldComponentUpdate for you and does a shallow compare on props and state -if there is no difference - component is not re-rendered. This is why PureComponent is used - to prevent unnecessary re-renders (perf boost) - make sure all child components of PureComponents are also Pure -never mutate state - always return new object that reflects the new state
What is Babel
- javascript compiler that includes the ability to compile JSX into regular JavaScript. - convert ES6 (or later) code into backwards compatible JavaScript . While most browsers support ES6 already, it's best practice to ensure you code is compatible with older versions. - JavaScript has syntax transformer plugins that let users employ the latest syntax - React's JSX isn't understood directly by browsers - Babel will compile JSX - Good Babel sandbox to type JSX or la
Redux - never mutate state
- never mutate state directly - like in the picture - always slice state and update attributes you need - it can lead to bugs/unpredictable behaviors (hard to debug) - always return brand new object (easy to accidentally mess this up with complex object) - redux toolkit createSlice() allows for us to mutate state directly (using Immer package internally)
Redux
- redux is one store for cross-app state - (authentication, theming, user input) - components subscribe to the store, and whenever data changes, it notifies component (component gets slice of data) - components don't directly manipulate data in store - they use reducer function - components dispatch actions (actions are simply js objects) -redux forward actions to reducer
Ref vs State Variables
- refs and state are similar - objects that contain values -update to state values can trigger re-render - refs can't trigger re-render. - refs persist across renders - but it does not cause re-render ( in a function component it's the only way to persist values across re-renders) ( in a class component you can persist values across re-renders - most popular use case is to directly reference an input element - also to store the previous value of your state Ref object: (stored in current { current: <your value here> } const [name, setName] = useState('') const prevName = useRef('') useEffect( () => { prevName.current = name }) warning => don't try to set the value of input or update values that should be managed by state - it will make code harder to work with https://www.youtube.com/watch?v=t2ypzz6gJm0
JSX
- short for JavaScript XML - write JavaScript with an HTML-like template syntax - its not html, not a string - just a template syntax inside js - template language produces elements that represent objects Difference b/w element and component? - element ==> created by JSX as an object (its a js object) - component ==> function that returns an object const element = <div>Hello</div> const component = () => <div>Hello</div> Can you write React without JSX? const Component = () => React.createElement('div', null, 'Hello')
props vs state
- state is used for variables used inside a component -props - are received from parent component and are read only -generally want to use 10% state, and 90% props throughout app - both are js objects
Stateful vs Stateless Components
- stateful components must be a class component - stateless component - can be a function or a class component - but generally use a function component unless you need a lifecycle method - As of react v16 - there are no performance benefits from using stateless functional components over class components
React constructor - super() vs super(props)
- super(props) should be used if you're going to call this.props inside the constructor -otherwise super() alone is sufficient. - need to call super() or super(props) in constructor - otherwise we can't use this (this will be undefined) ES6 class constructors MUST call super if they are subclasses
useContext
- useContext => provides a way to share data between components without having to pass down props manually through every level of component tree (prop drilling) - compared to redux , context is a simpler and lightweight solution for state management. Easier to get started with. (Doesn't have time travel debugging like redux) - useContext hook only makes consumption of context value simpler Usage: - create a Provider with some state you want to share - wrap a Consumer with provider tags <MyProvider> <MyConsumer /> </MyProvider> - in Consumer => useContext(MyContext)
useReducer - Reducer / Concepts (and comparison to useState)
- useReducer - an alternative to useState hook used for state management - useState is built under the hood using useReducer When to use useReducer vs useState - use useReducer to handle more complex state logic that require multiple actions to be performed. It provides a more structured approach to state manage that keeps the code organized and maintainable (especially as complexity of state and actions increases) - you can also pass the dispatch function down the tree useContext + useReducer (for global state mgmt) - you can also use useContext and pass the dispatch function in context to other deeply nested component (anywhere in the dom tree) state management in order from simple to complex useState < redux toolkit < (useReducer + useContext) < redux - simple state and action in example https://codesandbox.io/s/agitated-resonance-epvmm?file=/src/App.js
useReducer with useContext for global state management
- useReducer - for local state management - at some point we might want to work with global state by combining useReducer + useContext - Example: - do useReducer in top level component and wrap lower components in ContextProvider - Pass context provider value of state value and dispatch - useContext in lower level components that can dispatch https://codesandbox.io/s/react-hooks-usecontext-usereducer-counter-6h02x?file=/src/index.js
When should you use class component vs function component
- you should now always use function based components - all new features use function components Error boundaries - only available in Class Components
CSS-In-JS
-CSS is global, sass is also global - so changing css can impact other parts unintentionally. Passing css as js allows you to do inline css that does not effect other parts - css-in-js can also allow us to conditionally render - so if I have a prop I can conditionally render based on that -can import styles (share common styles) across your project
Project/Coding Question Categories
1) *Fix it for me* - program has some error. Want to know debugging techniques. Ie.. may be some event handlers not bound properly to the class, state may not be updating properly, or types - ask clarifying questions - use console.log() 2) *Add functionality* - a working project, add some more functionality on to it (extend it). IE.. given tic tac toe , add functionality to check who's the winner -draw out logic - don't start coding until you know the solution (and you must know all the requirements and constraints) 3) *Build it from scratch* - Ie: build todo list - add item, remove item, edit item etc.. - best to start with Create React App - always componentize - build into hierarchy of components - don't make it css fancy - use es6 syntax (instead of binding class properties - use arrow functions) - if you have time, write some test cases in jest 3b) Take home project - want hardworking and fast on their feet - may be a timeline - may be css guidelines - may ask initial questions - but usually not much support
Class Component vs Functional Component
1) Functional Component - simply take in props and display them - can't use lifecycle methods or state - we can't you ShouldComponentUpdate() - which is often used to optimize performance - can use ES6 arrow functions for more compact syntax (no function or return keyword. this in arrow function is lexically scopped - easier to test - can still have propTypes and defaultProps const Hello = ({ name }) => (<div>Hello, {name}!</div>); 2) Class Component - can have a constructor, state and lifecycle methods - best practice is to have a constructor with a call to super(props) - although technically only need super(props) if you're using this.props in constructor
React Lifecycle Methods
1) Mounting: constructor ==> getDerivedStateFromProps => render => componentDidMount 2)Updating (new props, setState, or forceUpdate) : getDerivedStateFromProps => shouldComponentUpdate => render => getSnapshotBeforeUpdate => componentDidUpdate 3) Unmounting: componentWillUnMount http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
Presentational Component vs Container Component
1) Presentational component - coupled with view or how things look. - should stay decoupled from behavioral layer - receive props and callbacks from container components - Ie.. a button is pressed and invoke callback to container component to handle click - presentational components are generally functional components 2) Container Components - deals with behavioral part. Container component tells presentational component what should be rendered using props. - shouldn't contain DOM markups and styles.
Context API vs Prop drilling
1) Prop drilling - explicitly stating props and values that a given child component can get - know exactly where values are passed at anytime, but they can be manipualted by accident 2) Context API because defined at top level and can be used at any level of the tree, you might have unnecessary rerenders
Redux Toolkit
1) Slice file - defines a slice of state - uses immer internally so you can modify state directly ( state.value +=1 - reducer functions should be pure , no side effects - a) Creating the slice - counterSlice = createSlice({ name: ...., initialState: { value: 0 }, reducers: { increment: (state,action) => { state.value+=1 }, incrementByAmount : (state,action => { state.value+=action.payload} }, b) Middleware/thunk export const incrementAsync = (amount) => (dispatch) => { setTimeout(() => { dispatch(incrementByAmount(amount)); }, 1000); }; c) Selecting the state value export const selectCount = (state) => state.counter.value; File that uses the slice const count = useSelector(selectCount); - button onClick => dispatch(incrementByAmount(Number(incrementAmount) || 0))
Where to Put Code? Fat Reducers vs Fat Components vs Fat Actions
1) Synchronous, side-effect free code - prefer to put logic in reducers -avoid actions creators 2) Async or code w/ side effects -prefer action creators or components (in RTK uiActions.toggle() calling an action creator that creates an action that we dispatch) - never use reducers Fat Reducer in Example -perform all logic in reducer (update cart) - then make fetch call using useEffect (cart as a dependency, make a call to firebase)
What causes poor React performance
1) Unnecessary re-renders - use react performance dev tools 2) high time complexity in render functions ( accidental quadratic loops) only focus on unnecessary re-renders and performance issues if you're seeing slowness - no need to do premature optimization
React Security Issues
1) XSS - use {} when binding data (applies for textContent not HTML attributes) - attributes need to be validated/sanitzed 2) Sneaky anchor links ==> <a href="javascript: mySneakyCode()"> - Fix ==> whitelist url or create your own Link component 3) DangerouslySetInnerHTML - use a sanitization library dangerouslySetInnerHTML={{__html: sanitize(data) }} 4) Server Side Rendering - can data leak if you're just doing a JSON.Stringify or appending strings to the rendered content 5) 3rd Party Libraries - keep packages updated, watch github for vulnerability notices - use third party services like Snyk 6) Linters - use ESLint React security configuration - configure pre-commit hook that fails when security related linter issues are detected (using library)
useEffect - when it's run, simplified
1) [ ] - runs on mount 2) [variable] - runs on mount and when variable changes 3) No array - runs on mount and every state change 4) useEffect with return function - called for cleanup / componentWillUnmount (clear set timers ) -typically not more than one or two variables in dependency arrays
How to visually hide content in React
1) conditional render (worse for accessibility) 2) display: none (more performant than conditional render 3) visibility: hidden, opacity: 0, heigh/max-height:0
React Top 5 Project Structure Mistakes / Suggestions
1) efficient project file structure - if something only used by that component, keep in folder with that component, if it starts to be cross component, raise to higher level 2) monolithic app - componentize everything so we don't have monolithic large files. Identify behavior/logic vs presentation component in planning process. Shouldn't have a bunch of lines in one file. 3) Business logic in re-usable components - most components should be stateless functional . All business logic should go in page , not underlying components 4) Have unit tests - when you change code you don't want to break anything - and ensure you have proper coverage (Jest has an option to see coverage) 5) Keep up with upgrades - if you wait too long you may encounter a bunch of problems. Take time out of schedule to have team upgrade and test a new version of react
In Redux - where should side effect / async code be?
1) inside the component (simple useEffect) - in this case we make an api call before calling redux 2) inside action creators - not the action creators RTK gives us, but write our own action creators
React Limitations
1) it's a library and not a framework - library enhances existing code (could write a big jquery app and have one small part be react) - react focuses on being the V in the MVC (if you want a framework you can use Gatsby, or NextJS) - some people need an opinionated framework 2) React is large - not a bad thing if you have code splitting, and a discerning way of writing components - preact is a smaller version of react 3) Being owned by Facebook - It is maintained by large company that makes sure it doesn't die - but cons are privacy concerns trusting Facebook, and transparency (even tho open source) trusting internal team 4) Documentation - doesn't touch on function components as much - a bit confusing / hard to navigate - because the learning curve for React is difficult
Best times to use Refs
1) managing focus (ie an input the cursor starts at) or media - Ex - open modal and input box - trigger modal and use ref to make sure input element is focused 2 triggering animations - IE - an animation that is imperative and not state drive 3) Integrating with DOM libraries - integrating with 3rd party dom libraries - where they need to be able to attach to some type of dom element w. react because it uses virtual dom, there's nothing to grab onto, so Ref gives something to grab onto
React Memo vs PureComponent
1) memo is for functional presentational components. Functional components don't have to lifecycle methods like shouldComponentUpdate or PureComponent option - memo only checks changes in props (not state) 2) PureComponent - is for class components -checks changes in both props and state
React Hooks Rules
1) only call hooks at top of function don't call hooks inside loops, conditions, or nested functions 2) Only call hooks from React Functional components - don't call from just a regular JS fn - only available in 16.8 or higher - completely opt in - all backwards compatible (classes will still be used - can't use hooks in class component
Why React hooks?
1) state management / share state across components - previously with class components you could only do this with HOC and render props pattern - useContext, useReducer, useState - the 2) custom hooks - - encapsulate complex/repetitive logic into a single, reusable function (separating the logic from your components) . Allows presentational components to stay lean and focus on UI rather than behavioral logic - EX => encapsulate form state management in a custom hook (IE.. useForm) - reuse this logic in other components that require form state management - making the code DRY'er - and making the code more modular/reusable 3) testability - hooks are just functions and are easier to test than the older class lifecycle methods without the need for complex setup/mocking - custom hooks has business logic that's separated from UI - which makes it easier to test just the biz logic separately 4) improved performance - useMemo and useCallback - can memoize expensive calculations and functions 5) less worrying about this when we use fn components - we don't have to bind event handlers in fn components - facebook plans performance improvement for functional components in the future - can easily convert stateless fn component to stateful component - no more complex hard-to-remember lifecycle methods - hooks are backwards compatible
Rendering: 1) stateless functional 2) React.Component 3) React.PureComponent 4)React.Memo
1) stateless functional - no shouldComponentUpdate() so always re-renders on prop change 2) React.Component - has a shouldComponentUpdate() that always returns true unless we write our own comparison against prevProps or prevState 3) React.PureComponent - automatically does a shallow comparison in shouldComponentUpdate(). This will pickup changes in immutable objects or in simple non-nested objects. 4) React.Memo - memoizes/caches previous render results with the same input values to boost performance. Good for representational or stateless/functional components - memo prevents re-render only if the props don't change. If the state of a functional component changes then it will re-render- however if the state of a functional component is set to the same value - it doesn't re-render
How to Reduce Perceived Page Load
1) static/cached content (pages that aren't stateful can be compiled and cached) 2) edge caching ==> CDN 3) Inlining-CSS (for above the fold content) - normally css must be downloaded before anything is rendered to page . An external css <link> from the server will require an additional network request. - performance approach is to put critical css directly in <head> (so no network request and initial load faster for above the fold content) and put non-critical css in an external file (that requires network load) 4) Limit layout shift (one of the web vitals) - caused by: - ads, embeds, iframes without dimensions - dynamically injected content - images without dimensions - actions waiting for a network response 5) Minimize HTTP requests: Each resource on a page (e.g. images, scripts, stylesheets) requires a separate HTTP request, which can slow down page load times. You can minimize HTTP requests by combining multiple resources into a single file, using image sprites, and avoiding unnecessary resources. 6) Optimize images: Large images can take a long time to load, so it's important to optimize them for the web. This can include compressing images, reducing their dimensions, and using the appropriate file format (e.g. JPEG, PNG, WebP). 7) Use a content delivery network (CDN): A CDN is a network of servers that can deliver content to users from a server that's geographically closer to them, which can reduce load times. 8) Lazy load content: Lazy loading is a technique where content is only loaded when it's needed, which can improve page load times by reducing the amount of initial content that needs to be loaded. 9) Minimize JavaScript and CSS: Large JavaScript and CSS files can significantly slow down page load times. You can minimize them by removing unused code, using code splitting to load only the necessary code, and minifying the code to reduce its size. 10) Use server-side rendering: Server-side rendering (SSR) can improve page load times by rendering content on the server before sending it to the client, which can reduce the amount of work that needs to be done by the client.
Advantages and Disadvantages of Testing
Advantages - prevents unexpected regression - allows the dev to focus on tasks rather than worrying about past - modular construction of app - reduces manual verification Disadvantages - write and maintain more code - non-critical test failures might cause the app to be rejected in terms of continuous integration
useState
Basic Usage: const [count, setCount] = useState(0) useState with prevState setCount( prevState => prevState + 1 ) useState updating Object setName({...name, lastName: e.target.value } ) -or- setName( prevName => {...prevName, lastName: e.target.value}) useState updating Array const [items, setItems] = useState([]) setItems([ ...items, {id:..., value: ...} ]) -or- setItems( prevItems => [...prevItems, {id:..., value: ...} ] ) - state variable can be a string, number, object, boolean, array (In class components the state has to be an object) -
Enzyme vs react-testing-library
Enzyme allows you to access the internal workings of components - set state or even mock children to make tests run faster - allows modifying and reading React component internals - not great because it makes test brittle (asserting component has the state `username` - rather than asserting that this state is displaying on the screen) - intended for unit / integration tests - limited async testing support React-testing-library - testing based on real DOM component output - not the component internals - intended for integration and e2e tests -no options for isolated unit tests - but possible to do it by mocking modules - official recommended testing library - can easily add accessibility testing - overall more reliable - by testing the behavior (and not component internals) - its more resilient to changes in the component internals (as long as the behavior remains the same)) - Both Enzyme and React-Testing-Library built upon react-dom/test-utils and react-test-renderer
useEffect
Lets you perform side effects in functional components (dom updates, data fetch, setting up subscriptions) - replacement for componentDidMount, componentDidUpdate, and componentWillUnmount componentDidMount useEffect( () => { //called only once }, [] ) componentDidUpdate useEffect( ()=> { //called everytime }) useEffect( ()=> { //called everytime w/ dependencies }, [dependencies] ) componentWillUnmount useEffect( () => { return () => { //cleanup (cancelling subscriptions, timers, or //removing event handlers } }, [] ) shouldComponentUpdate - use React Memo componentDidCatch - no substitute for this method yet in hooks - you can specify multiple useEffect in one functional component
React Immutable Architecture
Props is read-only and immutable State is mutable - every update creates a new value, which allows simple equality comparison to see if it's been updated. https://blog.logrocket.com/immutability-in-react-ebe55253a1cc/
React setState race condition - setState updater function signature
Race condition can lead to unexpected behavior: handleCount(value) { this.setState({count: this.state.count+100}); this.setState({count: this.state.count+value}); this.setState({count: this.state.count-100}); } To fix this, we can use the setState "updater" function signature: this.setState( (prevState, prevProps) => { count: prevState.count + 1 });
Why would you use react in your project? (as opposed to angular or vue)
Reasons to use React - Declarative programming - Large ecosystem => React is just a library so you have to bring in different resources whereas angular is a full mv* framework - build a component based architecture (atomic design, composition of components -UI testing is easier in react with jest/enzyme (in create-react app) - fast rendering = > virtual dom -cross platform support (web, and mobile with react Native / Electron) - React is JavaScript/JSX and this is more readable and easier for people who know javascript When to not use React - unfamiliar with javascript - React may be difficult to learn (maybe better to start with jQuery) - might steer away from react if react has a huge change coming - simple project - using plain html/css/js may be more straightforward - performance critical app => while React is fast, certain scenarios like building a real-time game or app performing complex calculations in real-time (using a lower level programming language may be more appropriate - static websites When to choose Angular or Vue - angular is a huge package that has angular specific things - whereas react is more javascript focused. If the team knows javascript, the learning curve is lower - angular might be better for large enterprise apps - since it provides more built-in features, such as dependency injection and robust routing features - Vue might be better for lightweight applications or rapid prototyping as it has a lower barrier to entry - The vue package is also the smallest - React is a one way binding , angular is two way binding
Virtual DOM vs Shadow DOM
Shadow DOM is a browser specific technology , not a pattern. Is for specific types of elements you don't need to code, used for styling -slider elements - don't need to write html for knob, only need to write slider, if you want to update it, you can use shadow dom to manipulate css Virtual DOM is a pattern built into react, vue
React-testing-library common interview q's
Shallow vs Full Render RTL - Shallow => only component being tested (not child) (render() -Full => render entire component tree (mount () ) getBy vs QueryBy - getby => throws an error if it can't find element - queryBy - returns null if it can't find element How to Simulate Events in RTL - fireEvent.click(button) RTL render() - renders component and returns a set of query methods to find elements RTL act() - wrap code that makes changes to component state or DOM - ensures all updates are complete before moving on with test RTL waitFor - waits for a specified amount of time for an element to appear on the page - or condition to be true before moving on render vs screen objects - render() => returns set of query methods to find elements in component - screen => object in RTL with methods that can query the whole document
Synthetic Events
Synthetic events are the objects which act as a cross-browser wrapper around the browser's native event. They combine the behavior of different browsers into one API. This is done to make sure that the events show consistent properties across different browsers.
useMemo vs useCallback
The useCallback and useMemo Hooks are similar. The main difference is that - useMemo returns a memoized value and - useCallback returns a memoized function.
useCallback
Use case => prevent a component from re-rendering unless its props have changed. - Every time a component re-renders, its functions get recreated. If that function is passed as a prop to a child component (even if the child component is using memo) - the child component will still re-render See => https://www.w3schools.com/react/react_usecallback.asp - only recreates function with dependency changes Syntax useCallback( () => { }, [mydependency] ) -useCallback - takes a function, and returns that function - useMemo - takes a function, and returns the return value of that function https://www.youtube.com/watch?v=tbBILjDgXb4
Virtual DOM vs Real DOM
Virtual DOM - can't directly update the real HTML - acts as a copy of the real DOM, which can be frequently manipulated and updated w/o page refresh - more of a pattern than specific tech (used in places outside react) - synced with real DOM with 'react-dom` Real DOM - directly updates and manipulates HTML (because it is an object based representations of HTML document) - creates a new DOM / full repaint w/ each update - Both an object based representations, and an interface for manipulating that object - key difference is that Virtual DOM does is diffing/reconciliation (just updates that particular part of the
When shouldn't use the Context API?
You shouldn't overuse the Context API - it can lead to unnecessary re-renders -be discerning about where you use Context API - only put what's absolutely necessary at the top level of app with Context, everything else , just make more context if they need to be shared, otherwise props are good way of sharing different state values and state - context is good for theme, authentication, something that shared across app tree - but not something where you need to keep track of a lot of clicks
Render Props
a technique for sharing code between React components parent component passes a prop that's a function down to the child component - child component calls that functions instead of implementing its own logic In child component => this.props.render() - can be used to share
static getDerivedStateFromProps() (and why is it static)
allows us to update state in response to prop changes. Used in rare cases where state depends on changes in props. Either: a) return state object updates b) return null if there is no change to state (this is default) -it's a static method because we don't want user to access 'this' keyword inside method (it's a static method not a class method) - prevents from making mistakes - such as doing this.setState or calling a class method
componentDidMount()
called as soon as component is mounted and ready -good place to initiate API calls -calling setState will update state and cause another render, but it will happen before the browser updates the UI to ensure that the user will not see any UI updates with the double rendering
componentWillUnmount()
called before the component is unmounted/destroyed Common cleanup activities performed in this method include, clearing timers, cancelling api calls, or clearing any caches in storage.
getSnapshotBeforeUpdate()
called right before render (dom update) useful for capturing info about the DOM , such as scroll position, before it is potentially changed
createRef vs useRef
createRef always returns a new ref - which you'd generally store as a field on class component instance useRef returns the same ref upon every render of functional component. - very similar to state, Use case: 1) persisting a value across re-renders when state will cause infinite loop - Ie.. if you want to count how many times a component has re-rendered - you can set a useRef const numTimesRerendered = useRef(0) - then in useEffect , update value (if you used a useState state variable for this, every re-render will cause a state update in useEffect - basically an infinite loop) 2) referencing specific elements https://stackoverflow.com/questions/54620698/whats-the-difference-between-useref-and-createref
Reducer Functions
general programming concept - take some input (r -ie reduce list of numbers to a sum) - in general transform and spit out new output redux uses this concept - reducer function should be a pure function a) deterministic - same input ==> same output b) pure - no side effects (affecting outside scope vars, or XHR/API calls) c) synchronous Input ==> (Old State) + (Dispatched Action) Output ==> New State Object (state output could technically be a primitive like Number, or String - but in real apps its almost always object)
react-dom vs react library
react - creates and defines UI react-dom ==> says how user interfaces defined get added to the DOM
React Enzyme mount options
shallow - renders individual components (not child components - so we can test component in isolation) mount - renders full DOM including child components render - render html
Custom Hooks
used whenever you want to share logic between functional components - a custom hook is just another function to make things easier convention is to name it ==> "useCustomHook" - if custom hook has a setter (not just a getter) - you can return the value and the function to update that value - if just returning 1 value you can also just return 1 value - 2 components using the same hook don't share state - hooks are just a way to re-use stateful logic
Code-Splitting (by route or by component
when react code compiles, the bundler usually creates a single bundle which is very large - this is problematic for a large application - initial load can be huge -sometimes users only visits a few pages. So react introduces a way to split code into multiple bundles - and each bundle is loaded on-demand, rather than loading hte entire code upfront 1) Route based code splitting - splitting the code based on routes in the app. (Ie an app w/ dashboard and settings page - code for each page split into separate files - so only code for currently active page needs loading) 2) Component-based code splitting - splitting the coe based on components in the application. (Ie. if the app has a rarely used complex component - the code for that component can be split into a separate file loaded only when that component is actually used) -using React.lazy - we can async/dynamically load the route so that the initial load is faster - sometimes rendered inside a <Suspense fallback={<div>loading...</div>} > -need to provide a fallback component to display while other bundle code is https://reactjs.org/docs/code-splitting.html
React unique key
- Each child in an array should have a unique "key" prop. -react uses the key prop in the reconciliation process (determining what's been updated between current and previous virtual dom). It's a performance issue. - If not keys are used in a map function, index is used as the default -don't use index as key if order of items may change When its ok to use id: ---------------------------- 1) the list and items are static-they are not computed and do not change; 2) the items in the list have no ids; (you should use the native list id's if possible) 3) the list is never reordered or filtered.
Thunk
- a function that delays an action until later - typically an action creator in Redux returns an action that we then dispatch - a thunk is an action creator that doesn't return an action itself, but it returns another function which eventually returns the action - dispatch() (from useDispatch) accepts both an action object and also a function (common pattern to have action creators create side effects and then dispatch actions) - dispatch(fn) ==> executions fn (gives dispatch argument automatically)
React Context (and context vs redux)
- a globally available prop that should be used when you need something that is going to be everywhere in the application - usually has a very specific use case - like translating text from anywhere in applications Best Practice => break context down into slices that only 1 or a few components use - since every update to context state causes re-renders in the useContext subscribers, we want to keep subscriber count small to each context provider
PropTypes and defaultProps
- prop types are a way for you to know what types a component is expecting. -only checks in development mode where it will throw a warning - similar to expressing type in flow or typescript -they often become legacy documentation and people forget to keep them updated - or they put ".required" on the wrong things
useMemo
-by wrapping a function in useMemo - it only runs when one of it's dependencies change 1) good for caching the value of slow running functions 2) referential equality - make sure reference of object/array is exactly the same as last time your rendered (none of internal key/val change) - use useMemo to make sure you only update when the contents of that object changes - instead of updating it every single render - when you update state in react, its going to re-render entire component - it might re-render a slow function - which is a performance problem function App(){ const [number, setNumber] = useState(0); const doubleNumber = useMemo( () => { return slowFunction(number }, [number] ) return (....) } function slowFunction(num){ for(let i=0; i<100000000; i++){} return num*2 } - don't want to memoize everything: - memory gets larger for each useMemo call - if you do it in unneeded places - only use it on super slow function -another use case ==> referential equality
ErrorBoundary - where does it catch errors
-catch errors in render, lifecycle methods, in constructors of whole tree below them - does not catch errors inside event handlers - need to use try/catch for event handlers
What is a portal?
-render children into a dom node, that exists outside of dom hierarchy of parent component - can live anywhere in dom tree - - performance increase since when parent re-renders, the portal content doesn't need to re-render (especially if it's a hidden modal) Ie - in a modal where modal lives separately from tree
shouldComponentUpdate()
-useful if you don't want to render after state or prop changes pure component - default does shallow check normal class component - default returns true
Different ways to conditionally render
1) if else 2) condition && <Component> 3) ternary operator
React Good Maintainability practices
1) modular components that can be re-used 2) small components , separation of conerns 3) Typescript 4) Documentation and tests
When to use fragments (<> vs React.fragment)
<> can cause problems in some editors. Support is not universal. <Fragment> will work everywhere. -whenever you render a component - you need a single child, can't just have multiple siblings bad: ---------- <A /> <B /> good: --------- <> <A /> <B /> </> of <React.Fragment> <A /> <B /> <React.Fragment />
Error Boundaries and getDerivedStateFromError / componentDidCatch
A component becomes an error boundary component if you implement one of the two following methods: 1) getDerivedStateFromError - something broke in one of component descendants -update state to display an error: static getDerivedStateFromError(error) { return { hasError: true };} -used for a fallback UI after error 2) componentDidCatch - similar to getDerivedStateFromError but we can now perform any side effects like logging the error. -only works for error in the render/lifecycle methods (not in event handlers) - most commonly used for catching and logging errors Error Boundary do not catch: - event handlers - async code ( setTimeout ) - server side rendering - errors thrown in the error boundary itself (rather than children) https://reactjs.org/docs/error-boundaries.html
Controlled Component
Component that has the value of form inputs controlled by React state. - react controls state changes, react drives it (jQuery can't touch it, user might not be able to manage it) Uncontrolled - react doesn't control https://reactjs.org/docs/forms.html#controlled-components
React one-way binding vs Angular two-way binding
Angular => through angular scope variable - and using the ng-model directive, - watchers directly push view updates into model React - updates in the view need to flow through an event handler https://stackoverflow.com/questions/34519889/can-anyone-explain-the-difference-between-reacts-one-way-data-binding-and-angula
State in a class component vs state in a function component
Class Component - state in a class component is using a function called this.getState - state in class comp - state in class component is attached to class object, -the component in react class is an object, and the state is something that persists across that class component Functinoal Component - state in a fn component is something is recalled multiple times, because a fn component is not a function that persists over times or is manipulated - recalled every time state changes - state in a function component is something that is recalled/reinstantiated, because a functional component is recalled/reinstantiated
ErrorBoundary in production vs dev
Errors in dev will show the actual error (as if you had no fallback UI) - but if you click the x on the error - it will show the fallback UI as it would in production - componentDidCatch ==> errors automatically logged in development (so if you log an error to console you'll see it twice)
How to optimize react app
How big is the app? which version of react? What are you trying to optimize - is it crashing, bundle size or what? 1) Speed issues: --------------------- -run a profiler to find bottlenecks (which area behaving poorly) -might have unnecessary re-renders. To fix this we can use shouldComponentUpdate(), React.PureComponent, or React.memo - use React.lazy to lazy load certain routes - may find API is slow - improvement needed on server side - assets could load slowly - use CDN (cdn has globally distributed servers that cache requests) - may be using classes for presentational components - may be using traditional class functions for event handlers - switch to arrow functions -React perf tools
Pure Functions
The Chrome V8 engine can optimize this code by saving/caching/memoizing the result 1) Deterministic - for specific input params, always have a specific output. // This is an impure function since it is dependent on a // variable outside the function var initialValue = 10; function addData(newValue) { return initialValue + newValue; } // this is also impure since it modifies a variable outside // the function var getInitialValue = 0; function getValue(inputValue) { getInitialValue = inputValue; return getInitialValue; } // this is a pure function function addData(firstInput, secondInput) { return firstInput + secondInput; } 2) Pure Function should not introduce side effects - modifying external var or obj property -logging data to console -writing data to file or network - triggering external process or async call - calling other functions w/ side effects
PropTypes vs Typescript
Typescript validates types at compile time, whereas -useful when you are writing code: it will warn you if you pass an argument of the wrong type to your React components, give you autocomplete for function calls, etc. - proptypes can generate typescript PropTypes are checked at runtime. - useful when you test how the components interact with external data, for example when you load JSON from an API. PropTypes will help you debug (when in React's Development mode) why your component is failing by printing helpful messages like:
Test Mocking (Jest.fn, mock, spyOn)
a duplicate of an object or module without any inner workings Mocking reduces the number of dependencies (the number of related files loaded/parsed when test is run) - so it makes tests execute more quickly - also known as spies - spy on behavior of function that is called by some other code Mock Functions - Jest.fn() - mock a single function - Jest.mock() - mock a whole module - Jest.spyOn() - capture info about how function was called
React as "declarative"
imperative code tells how to perform each step. Imperative uses statement that change a program state. declarative code tells what it wants to be done and defers execution. It expresses the logic of a computation without describing its control flow. React is declarative because we define what we want and let react handle the dom updates and virtual tree etc...
Higher Order Component (HOC)
take a component as one of the arguments and they return a new Component that has some added/enhanced functionality. - - used for reusing component logic (pattern that emerged from ReacT) const renderWhen = (condition, Component) => props => condition(props) ? <Component {...props} /> : null ); const EnhancedLink = renderWhen(({invisible}) => !invisible, 'a'); https://stackoverflow.com/questions/45935409/understanding-react-higher-order-components - withRouter is an example of HOC - typically start with keyword with
Thunk animated gif
thunk is just a function / action creator - just a middleware function that intercepts a dispatch, makes an api call, then makes the respective dispatch again
React Testing Types w/ Jest
unit test - test a small piece of code, units of code, or components. A unit could be a function or object. Tests a section of code in isolation . Usually done with shallow render component test - tests on component in isolation from other components. snapshot test - captures code of a component at a moment in time - to compare it to a reference snapshot file - keeps track of changes in app's UI. code representation of snapshot is a JSON file that shows what component looked like when snapshot made. -requires enzyme-to-json package -when test firsts run, snapshots got to snapshots directory - then all future runs of test are compared to that snapshot - if UI changes, you can update snapshot if it was a purposeful change integration tests - test how components interact with each other (useful for when we have lots of composed components) . Test if a child component can update context state in a parent end-to-end test - testing the whole system w/ real data to see if everything works as expected -any file found in the `__test__` directory or .spec.js or test.js suffix are considered a test Enzyme: ---------------- mount( <Component />) - full dom rendering for API calls or lifecycle methods or integration testing shallow(<Component />) - render component in isolation, to test component as unit render() - render components to static html