- Suspense
 
- HOCs (lazy, memo)
 
- Hooks
 
- Concurrent Mode
 
- Fiber Architecture
 
- 
Title - parent node
 
- 
It would render the whole app, then create VDOM tree from the render output, then connect to real DOM tree.
 
- 
Adapted by Vue, Elm, Hyper, etc.
 
- 
Problem is it blocks the main thread process.
 
- 
Two phases: Render phase and commit phase
 
- 
Render phase, not eager, it gives time for higher-priorirty process to happen.
 
- 
Once render phase, commit phase happens.
 
- 
Render phase: render function (functional components or render method of classes), constructors
 
- 
Commit phase: Lifecycle methods (componentDidMount) and effect hooks (useEffect and useLayoutEffect)
 
useEffect(() => {
  const listener = () => {
    setState((current) => {
      if (!is(current, store.getValue())) {
        return store.getValue();
      }
      return current;
    });
  };
  // Let's assume that the state has changed at this point
  listener();
  // Further updates
  const unsubscribe = subscribe(listener);
  return unsubscribe;
}, [store, subscribe]) 
- render per component, commit immediately
 
- hydration
 
- getServerSideProps -> renderToHTML -> hydrate (connect pre-rendered tree to the initial VDOM tree)
 
ReactDOM.render(<App />, document.getElementById(root));
const root = ReactDOM.createRoot(document.getElementById(root));
root.render(<App />)
 
const { data, error } = useSWR(`/api/user`); 
render-then-fetch
const [data, setData] = useState();
const [error, setError] = useState();
useEffect(() => {
  fetcher().then(setData, setError);
}, []);
return { data, error }; 
function UserDetails() {
  // ???
  const userDetails = userDetailsFetcher.read();
  return (
    <>
      <h1>{userDetails.name}</h1>
      <h1>{userDetails.age}</h1>
    </>
  );
}
<Suspense fallback={<h1>Loading</h1>}>
  <UserDetails />
</Suspense> 
- memorize a single value/reference for the whole lifecycle
 
- refs are not reactive.
 
- capturing DOM
 
- states
 
- reactive
 
- bail-out mechanism
 
const [count, dispatch] = useReducer((state, action) => {
  switch (action.type) {
    case 'INCREMENT':
      return state + 1;
    case 'DECREMENT':
      return state - 1;
    default:
      return state;
  }
}, 0); 
- useEffect != componentDidMount
 
- Always ideal for side-effects
 
- Only runs once on strict mode and concurrent mode
 
- useEffect always runs after useLayoutEffect
 
- useLayoutEffect == componentDidMount
 
useLayoutEffect(() => {
  inputRef.current.addEventListener('click', listener);
}, []);
<input ref={inputRef}> 
- Presents debug value on devtools
 
- Receives the forwarded ref, decorates value
 
const Input = forwardRef((props, ref) => {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    value: inputRef.current.value,
  }));
}); 
- memoizes a value from a function
 
- recomputes when dependencies change
 
- unstable
 
useConstant(expensiveFunc);
const value = useMemo(expensiveFunc, []);
 
<div onClick={() => {
  // ...
}}> 
const Example = createContext({ a: 'Hello', b: 'World' }, (prev, next) => {
  if (prev.a !== next.a) {
    return 0b01;
  }
  if (next.b !== prev.b) {
    return 0b10;
  }
  return 0b00;
});
//
const { a } = useContext(Example, 0b01);
// 
const value = useContext(Example, (state) => newState);