React Trivia Flashcards
Angular vs. React
- AngularJS approaches building an application by extending HTML markup and injecting various constructs (e.g. Directives, Controllers, Services) at runtime.
- AngularJS is very opinionated about the greater architecture of your application
- Example: Input fields and model data are bound together, and will each automatically update as the other is changed. So as a user is typing into an input field, the corresponding model will be updated simultaneously.
- React focuses exclusively on the creation of components, and has few (if any) opinions about an application’s architecture.
- This allows a developer an incredible amount of flexibility in choosing the architecture they deem “best”
- Example: The input is not directly manipulating the state. Rather, the input will trigger an event, which the component can listen for, and then update its state. The view is then re-rendered as necessary based on the new state.
What is React
- Lightweight JS library used to build user interfaces
- View of MVC
-
A Declarative API
- You don’t need to know how React is making changes to the view.
- You just need to tell React what to do, and you don’t need to worry about the implementation details.
-
Virtual DOM
- Stores state in vanilla JS vs. DOM
- React updates the state in JavaScript before determining which DOM nodes it needs to change
- FAST
- Component-based design Create modular, reusable, single purpose components
-
One-way data flow
- application state (single source of truth) that can change should be owned by one component,
- there should be one single source of truth for every piece of application state
(regular) Components vs. Pure Components
- Not as performant
- Will re-render by default whenever shouldComponentUpdate is called
- Example: If parent is updated, all children consuming the prop/state will update as wel
- Improves performance of app
- Will do a shallow comparison before deciding to re-render or not (tries to avoid unnecessary re-renders)
- Shallow comparison on state change which means:
- scalar values: compares values (string, number, etc.)
- objects: compares references (sets, objects, arrays)
- Handles the shouldComponentUpdate method for you
- Good for:
- state/props should be an immutable object
- state/props should not have a hierarchy
- hierarchy: objects within objects
- non-hierarchy: primitives
- Stores state
- Syntax: more code & requires you to extend from React.Component
- Can also use lifecycle methods
- Reads props from this.props (which could change during a re-render midway through an async req)
Before Hooks
- Syntax: plain JavaScript function
- Much easier to test (no state/lifecycle hooks)
- Cleaner and less code, more performant
- Good small UI where re-render cost won’t matter that much
- Makes you think about state: Container vs. Presentational components
- Function components capture the rendered values (using closure).
After Hooks
- Can now store state + lifecycle hooks
Further:
If we say that a “UI is conceptually a function of current application state”, the event handlers are a part of the render result — just like the visual output. Our event handlers “belong” to a particular render with particular props and state.
Class components read props from this.props. So if our component re-renders while making an async req, this.props will change and our callback is not “tied” to any particular render, and so it “loses” the correct props.
Instead, we can rely on JS closures and capture props at the time of render (see picture) and set props to the correct version of state for a particular render. In Functional components, this is what happens… it receives a version/copy of props that is specific to a particular render and doesn’t read directly from this
, but an instance of props.
https://overreacted.io/how-are-function-components-different-from-classes/
props and state = immutable
- you never mutate the prop or state object directly. In order to change state, you create a new instance of state with the changes you want
“this” = mutable
- “this” can change with UI. if you change the profile to someone else, “this” now refers to that new person, not the old one
This is important because functional components can rely on the correct instance of state to be used in a particular callbacks/event handler + render call. In other words, our event handlers “belong” to a particular render with particular props and state. That is because props/state is immutable (no side-effects) and even if state changes since a particular callback trigger/render, our callback is tied to a specific instance of state and render it was called with and b/c the state object itself doesn’t change, the new state/prop simply points to a different object entirely.
Example: You have an app where you can click follow on a person and receive a confirmation when it’s finished. If you click “follow” on PersonA, but switch profiles to PersonB midway through the async update, the confirmation message would say “You have successfully followed PersonB” if using Class components.
What to avoid in the React render() function
- General idea: don’t create new functions, objects or arrays in the re-render method (esp. wrt to state/props)
- Avoid deriving data in the render method: if data is defined inside render(), it is redefined everytime the component re-renders which means it gets a brand new reference each time (even if the derived data is the same) thus unnecessarily rendering
-
Don’t bind values in functions: every time the parent’s render method is called, a new function (with a new reference) is created to be passed to the child thus causing unnecessary re-renders even if the data itself is the same
- Parent needs to pass likeComment callback and user.id to child
- see attached pics for examples
React PropTypes vs. Static Type Checking (Typescript/Flow)
- Verifies data type at runtime (dynamically)
- Dynamically typed languages: JavaScript, Python, Ruby
- Errors are found at runtime, meaning your program will compile but it may not execute properly
- optimize programmer efficiency (implement w/less code)
- Verifies data type at compile-time (static)
- Static typed languages: C, C++, C#, Java
- It’s much easier to catch errors sooner, because your program won’t be able to compile
- Fail Fast Principle: compile-time data type checking is preferred because of the Fail Fast Principle where you want to detect bugs earlier leading to fewer defects in production code
- optimize for hardware efficiency (code executes as quickly as possible)
What happens during the lifecycle of a React component?
At the highest level, React components have lifecycle events that fall into three general categories:
-
Initialization:
- constructor runs and initial state is sets and methods are binded
- componentWillMount: since this runs before render, the component is not yet rendered and setting state in this phase will not trigger a re-render
- render: markup is added to the DOM
- componentDidMount: you can start accessing the DOM here and common for AJAX
- State/Property Updates
- Destruction
Use the componentDidMount life cycle method for AJAX requests
Use the componentWillUnmount method to clean up any state the component needs to remove
Presentational vs. Container components
Presentational components (stateless): mainly concerned with receiving the data via props and displaying them. They don’t specify how the data is loaded or mutated and don’t have their own states.
Container components (stateful): passes the data and behavior to presentational or other container components. They have their own states. You can generate the data here and pass it to presentational components.
How does React exhibit Object Oriented Programming (OOP) and Functional Programming (FP)?
OOP (but really OLOO): it doesn’t really… maybe some examples: extending the React class (but you shouldn’t ever extend further than that) & reusability of objects (but components are actually functions)
FP: components themselves are actually functions and with the new hooks, we don’t really need Class components anymore so it’s leaning towards functional programming
What if you don’t want the render to reflect the current state/props from that render and instead reference the latest state/prop?
How to make Functional components refer to “future” or most updated state (i.e. not tied to the state/prop of a particular callback/render)
useRef
React Classes: Why bind methods in Class components?
When a JS or React Class’ method is defined and then passed elsewhere (i.e. used in a callback either in its render() or subcomponent’s render), it immediately loses context of its original this.
In JS, “this” is the outer context of where the function is invoked (aside from arrow functions). If you call the instance’s method directly like so…
const componentInstance = new Component()
componentInstance.handleClick()
…then you’re fine. But most of the time, you’re passing it as a callback and as such, it’s called outside of its original outer context and therefore requires a .bind() to work.
See attached picture for an example.
How does React determine which part of the DOM to update?
(see attached)
A component has a useEffect() where it triggers a callback(number).
On first render, number = 10;
On second render, number = 20;
What is the sequence of events?
- React renders UI for new props
- Browser paints the new UI (for new props)
- React runs any effect cleanups from previous render
- React runs any effects for new/current render
— i.e. —
- React renders UI for number = 20;
- Browser paints UI for number = 20;
- React runs cleanup (from prev render) for number = 10;
- React runs effect (from curr/new render) for number = 20;
NOT this:
- React cleans up the effect for {number: 10}.
- React renders UI for {number: 20}.
- React runs the effect for {number: 20}.