REACT, REDUX, CONTEXT, USEREDUCER, USESTATE, USEEFFECT A whole lotta state and some side effects. Essentially all the functions below add state to React, and React will check for changes, and decide if a re-render is necessary. USESTATE Used for a component which requires to keep state between renders. const [state, setState] = useState(initialState); setState(newState); Order matters when you have multiple useState calls! "If you update a State Hook to the same value as the current state, React will bail out without rendering the children or firing effects." CONTEXT https://reactjs.org/docs/context.html#when-to-use-context Basically: when you want to pass state to a branch of a component tree. // Happens *once*. Do no evaluate more than once. const SomeContextObject = createContext("nameOfContext"); const value = useContext(SomeContextObject); "The current context value is determined by the value prop of the nearest above the calling component in the tree." Even if an ancestor uses React.memo or shouldComponentUpdate, a rerender will still happen starting at the component itself using useContext." USEREDUCER "An alternative to useState" " you can pass dispatch down instead of callbacks." Observe the relations in the code, it is quite simple: function reducer(state, action) { switch(action.type) { case 'thing': return { prop: 2 }; default: ... } } const [state, dispatch] = useReducer(reducer, initialArg, init); Almost exactly like redux. react-rewind gives the ability to move between all states of the app, easier to debug with. WHY USE REDUX AT ALL? (Nicely articulated by https://blog.isquaredsoftware.com/2021/01/context-redux-differences/) Redux is most useful in cases when: * You have larger amounts of application state that are needed in many places in the app * The app state is updated frequently over time * The logic to update that state may be complex * The app has a medium or large-sized codebase, and might be worked on by many people * You want to be able to understand when, why, and how the state in your application has updated, and visualize the changes to your state over time * You need more powerful capabilities for managing side effects, persistence, and data serialization PRESENTATIONAL, PURE, FUNCTIONAL STATELESS, DUMB COMPONENTS These types of components go by many names and have only one job, and that's to render the information given to them. Typically this information is passed in through a component's properties. The most accurate name for these components in my opinion is "functional stateless components", for the following reason: .... function statelessComponent(property1, property2) { return `
Some text: ${property1}
`; } .... CONTAINER, SMART, FUNCTIONAL STATEFUL, SMART COMPONENTS The opposite to those components, are stateful or "smart" components, which can encapsulate complex logic and side-effects to be reused. Once again, in my opinion the most accurate thing to call these are "functional stateful components", because you write functions that hold state. `CONNECT' OR USING REACT-REDUX TO MAKE YOUR LIFE PLEASANT .... import { connect } from 'react-redux'; const statesToProperties = state => ({ thing: state.ok }); const dispatchFunctionsToProperties = state => { func1: () => dispatch({ type: TYPE' }) }; connect( statesToProperties, dispatchFunctionsToProperties )(functionalStatelessComponent); .... USECALLBACK Use this when you have a function that may change, and need to pass it to child components. This will memoize the component, preventing the child components from rerendering if it didn't change. const memoizedCallback = useCallback( () => { doSomething(a, b); }, [a, b], ); USEEFFECT Runs after a render to the screen. The invocation should trigger your memories: useEffect(() => { const subscription = props.source.subscribe(); return () => { // Clean up the subscription subscription.unsubscribe(); }; // Bail if none of these changed // aka "conditional effect" }, [variableToWatch1, variableToWatch2]);