Pies Doc

website·Indexed 29 days ago

https://piesdoc.com/

Documentation and guides for React and Vue 3, covering core concepts such as hooks (useState, useEffect, useRef), component rendering, reactive values, and Vue 3 essentials including ref(), reactive(), composables, and props.

Tokens
14.2K
Snippets
63
Records
85
Agent score
50%

What's inside Pies Doc

  1. Overview of Pies Doc and its goals

    Pies Doc is a free handbook designed to help developers improve code quality by focusing on the fundamentals of APIs and the theory behind their usage. Rather than analyzing raw source code, it emphasizes correct API usage to help developers identify anti-patterns and reduce bugs caused by inappropriate implementation.
  2. Understand the useEffect hook lifecycle

    useEffect() is a built-in React hook used to handle side effects (e.g., state changes that happen indirectly). It takes a callback function and an optional dependency array.

    Execution flow:

    1. Mounting: The callback is always called immediately after the component mounts.
    2. Re-rendering:
      • If dependencies is undefined, the callback runs on every render.
      • If dependencies is an array, React uses Object.is() to compare each element with the previous render. The callback runs only if at least one element has changed.
      • If dependencies is an empty array [], the callback never runs during re-renders.
    3. Cleanup: If the callback returns a function, React calls that cleanup function before the next effect execution and immediately before the component unmounts.
    useEffect(() => {
      // Effect logic here
    }, [dependency1, dependency2]);
  3. Prerequisites for using Pies Doc

    Pies Doc is designed for developers who have a basic understanding of JavaScript and some foundational knowledge of the subject they are studying. Absolute beginners with zero experience may find the content difficult. To prepare, it is recommended to complete a basic official tutorial, such as building a simple todo or counter app.
  4. Understand React Hooks fundamentals

    Hooks are functions called at the root level of a function component. They allow you to encapsulate logic and return any value (or nothing) to the component.

    Distinctions:

    • vs. Utility Functions: A function is considered a 'hook' if it uses React-specific features (e.g., useState, useEffect).
    • vs. Components: Components are named with a capital letter and invoked via JSX (<Foo />). Hooks are named with a use prefix and invoked as standard function calls. Returning JSX from a hook does not make it a component.
  5. Understand state batching in React

    Batching is the process where React groups multiple state updates into a single re-render to improve performance and prevent UI flickering.

    • React 18+: All updates are batched by default, regardless of where they originate.
    • Pre-React 17: Only updates inside React event handlers (e.g., onClick, onChange) were automatically batched.
    • Behavior: If multiple setState calls are made within a single function, React will process all update schedulers first and perform only one render using the final calculated values.
    const [name, setName] = useState('');
    const [count, setCount] = useState(0);
    
    const updateData = () => {
      setName('A');
      setCount(1);
      setName('B');
      setCount(2);
      setName('C');
      setCount(3);
      // Component re-renders only ONCE with name='C' and count=3
    }
  6. Learning objectives and benefits of Pies Doc

    Pies Doc focuses on the fundamentals of the API and the theory behind it rather than raw source code analysis. By mastering these fundamentals, developers can identify anti-patterns and reduce bugs or inefficient workarounds caused by improper API usage, providing a necessary foundation for comprehending advanced technical knowledge.
  7. Understand how reactive values behave during React renders

    In React, every render has its own unique set of props and state. Reactive values (like those from useState) do not change their value within a single render; they act as constants for the duration of that render. When a state update is triggered, React schedules a re-render. The updated value is only available in the next render cycle. This explains why a console.log immediately following a setCount call, or inside a setTimeout closure from a previous render, will still show the old value: they are referencing the variable binding from the render in which they were created.
  8. Understand reactive values and component re-rendering

    In React, a reactive value is any value that, when changed, triggers the component to re-render. Re-rendering means React runs the component code from top to bottom to produce new JSX, which is then used to update the DOM during the commit phase.

    Reactive values include:

    • Values generated by useState()
    • Values generated by useReducer()
    • Component props

    Note on Context: Values from createContext() are only reactive if the context value and its update function are themselves generated using useState() or useReducer(). If a non-reactive value is placed in context, updating it will not trigger a re-render.

  9. Determine when to make a variable reactive

    Follow this rule of thumb when declaring variables in React:

    • Make it reactive: If the value will change AND the user must see that change reflected on the screen immediately.
    • Keep it non-reactive: If the value changes but does not need to trigger a UI update, or if the value is static.
  10. Extract complex effect logic into custom hooks

    To improve component readability and organization, move complex useEffect logic and its supporting helper functions into a custom hook. This is recommended even if the hook is only used within a single component, as it removes noise from the main component body and encapsulates the effect's behavior under a descriptive name (e.g., useSyncUser).
    import { useSyncUser } from './UseSyncUser'
    
    export const Example = (props) => {
      // The complex effect logic is now encapsulated
      useSyncUser(props)
    
      return (
        <div>...</div>
      )
    }
  11. Prevent child re-renders using useCallback and memo

    When passing a function as a prop to a child component wrapped in memo(), the child will still re-render if the function is redeclared on every render of the parent (because functions are non-primitive values). To prevent this, wrap the function in useCallback().

    To avoid adding state variables to the useCallback dependency array (which would trigger the function to be recreated), use an updater function within the state setter (e.g., setCount(prev => prev + 1)).

    import { memo, useState, useCallback } from 'react'
    
    const MemoizedChild = memo(({ increment }) => {
      console.log('Child rendered');
      return <button onClick={increment}>Increment</button>
    })
    
    export const Example = () => {
      const [count, setCount] = useState(0)
    
      // useCallback ensures the function reference stays the same
      // The updater function (prev => prev + 1) removes the need for 'count' in dependencies
      const increment = useCallback(() => {
        setCount(prev => prev + 1)
      }, [])
    
      return (
        <div>
          <h1>Count: {count}</h1>
          <MemoizedChild increment={increment} />
        </div>
      )
    }
  12. Memoize values and calculations with `useMemo()`

    useMemo() is a hook used to memoize a value. It takes a callback function and a dependency array. The callback is executed on the first render, and the result is cached. On subsequent renders, the callback is only re-executed if one or more elements in the dependency array have changed (checked via Object.is()).

    Common use cases:

    1. Expensive Calculations: Avoid running heavy logic (like filtering large arrays) on every render.
    2. Referential Stability: Ensure non-primitive values (objects, arrays) maintain the same memory address across renders. This is critical when passing such values as props to a component wrapped in memo(), as a new object reference would trigger a re-render.
    3. Replacing useEffect + setState: When a value can be derived directly from existing props or state, useMemo is cleaner and more performant than updating a separate state variable inside an effect.
    import { useState, useMemo } from 'react'
    
    export const Example = ({ keyword }: { keyword: string }) => {
      const [users] = useState([
        { id: 1, name: 'User A' },
        { id: 2, name: 'User B' },
        { id: 3, name: 'User C' },
      ])
    
      // 1. Skipping expensive calculations
      const matchedUsers = useMemo(
        () => users.filter((user) => user.name.includes(keyword)),
        [users, keyword]
      )
    
      // 2. Maintaining referential stability for objects
      const userConfig = useMemo(() => ({
        age: 5,
      }), [])
    
      return (
        <div>{/* Render matchedUsers and userConfig */}</div>
      )
    }